diff options
Diffstat (limited to 'roms/skiboot/external/common')
-rw-r--r-- | roms/skiboot/external/common/.gitignore | 3 | ||||
-rw-r--r-- | roms/skiboot/external/common/arch_flash.h | 38 | ||||
-rw-r--r-- | roms/skiboot/external/common/arch_flash_arm.c | 374 | ||||
-rw-r--r-- | roms/skiboot/external/common/arch_flash_arm_io.h | 86 | ||||
-rw-r--r-- | roms/skiboot/external/common/arch_flash_common.c | 50 | ||||
-rw-r--r-- | roms/skiboot/external/common/arch_flash_powerpc.c | 242 | ||||
-rw-r--r-- | roms/skiboot/external/common/arch_flash_powerpc_io.h | 0 | ||||
-rw-r--r-- | roms/skiboot/external/common/arch_flash_unknown.c | 42 | ||||
-rw-r--r-- | roms/skiboot/external/common/arch_flash_unknown_io.h | 0 | ||||
-rwxr-xr-x | roms/skiboot/external/common/get_arch.sh | 11 | ||||
-rw-r--r-- | roms/skiboot/external/common/rules.mk | 76 |
11 files changed, 922 insertions, 0 deletions
diff --git a/roms/skiboot/external/common/.gitignore b/roms/skiboot/external/common/.gitignore new file mode 100644 index 000000000..3535d9768 --- /dev/null +++ b/roms/skiboot/external/common/.gitignore @@ -0,0 +1,3 @@ +ast-sf-ctrl.c +ast.h +io.h
\ No newline at end of file diff --git a/roms/skiboot/external/common/arch_flash.h b/roms/skiboot/external/common/arch_flash.h new file mode 100644 index 000000000..0dff8b704 --- /dev/null +++ b/roms/skiboot/external/common/arch_flash.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* Copyright 2015 IBM Corp. + */ + +#ifndef __EXTERNAL_ARCH_FLASH_H +#define __EXTERNAL_ARCH_FLASH_H + +#include <getopt.h> +#include <libflash/blocklevel.h> + +enum flash_access { + PNOR_DIRECT, + PNOR_MTD, + BMC_DIRECT, + BMC_MTD, + ACCESS_INVAL +}; + +int arch_flash_init(struct blocklevel_device **bl, const char *file, + bool keep_alive); + +void arch_flash_close(struct blocklevel_device *bl, const char *file); + +/* Low level functions that an architecture may support */ + +/* + * If called BEFORE init, then this dictates how the flash will be + * accessed. + * If called AFTER init, then this returns how the flash is being accessed. + */ +enum flash_access arch_flash_access(struct blocklevel_device *bl, + enum flash_access access); + +int arch_flash_erase_chip(struct blocklevel_device *bl); +int arch_flash_4b_mode(struct blocklevel_device *bl, int set_4b); +int arch_flash_set_wrprotect(struct blocklevel_device *bl, int set); + +#endif /* __EXTERNAL_ARCH_FLASH_H */ diff --git a/roms/skiboot/external/common/arch_flash_arm.c b/roms/skiboot/external/common/arch_flash_arm.c new file mode 100644 index 000000000..cfe7b96aa --- /dev/null +++ b/roms/skiboot/external/common/arch_flash_arm.c @@ -0,0 +1,374 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* Copyright 2015-2016 IBM Corp. + */ +#define _GNU_SOURCE +#include <stdlib.h> +#include <stdio.h> +#include <limits.h> +#include <unistd.h> +#include <dirent.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <assert.h> + +#include <ccan/container_of/container_of.h> + +#include <libflash/libflash.h> +#include <libflash/file.h> +#include "ast.h" +#include "arch_flash.h" +#include "arch_flash_arm_io.h" + +struct flash_chip; + +static struct arch_arm_data { + int fd; + void *ahb_reg_map; + void *gpio_ctrl; + size_t ahb_flash_base; + size_t ahb_flash_size; + void *ahb_flash_map; + enum flash_access access; + struct flash_chip *flash_chip; + struct blocklevel_device *init_bl; +} arch_data; + +uint32_t ast_ahb_readl(uint32_t offset) +{ + assert(((offset ^ AHB_REGS_BASE) & ~(AHB_REGS_SIZE - 1)) == 0); + + return readl(arch_data.ahb_reg_map + (offset - AHB_REGS_BASE)); +} + +void ast_ahb_writel(uint32_t val, uint32_t offset) +{ + assert(((offset ^ AHB_REGS_BASE) & ~(AHB_REGS_SIZE - 1)) == 0); + + writel(val, arch_data.ahb_reg_map + (offset - AHB_REGS_BASE)); +} + +int ast_copy_to_ahb(uint32_t reg, const void *src, uint32_t len) +{ + if (reg < arch_data.ahb_flash_base || + (reg + len) > (arch_data.ahb_flash_base + arch_data.ahb_flash_size)) + return -1; + reg -= arch_data.ahb_flash_base; + + if (((reg | (unsigned long)src | len) & 3) == 0) { + while(len > 3) { + uint32_t val = *(uint32_t *)src; + writel(val, arch_data.ahb_flash_map + reg); + src += 4; + reg += 4; + len -= 4; + } + } + + while(len--) { + uint8_t val = *(uint8_t *)src; + writeb(val, arch_data.ahb_flash_map + reg++); + src += 1; + } + return 0; +} + +/* + * GPIO stuff to be replaced by higher level accessors for + * controlling the flash write lock via sysfs + */ + +static inline uint32_t gpio_ctl_readl(uint32_t offset) +{ + return readl(arch_data.gpio_ctrl + offset); +} + +static inline void gpio_ctl_writel(uint32_t val, uint32_t offset) +{ + writel(val, arch_data.gpio_ctrl + offset); +} + +static bool set_wrprotect(bool protect) +{ + uint32_t reg; + bool was_protected; + + reg = gpio_ctl_readl(0x20); + was_protected = !!(reg & 0x00004000); + if (protect) + reg |= 0x00004000; /* GPIOF[6] value */ + else + reg &= ~0x00004000; /* GPIOF[6] value */ + gpio_ctl_writel(reg, 0x20); + reg = gpio_ctl_readl(0x24); + reg |= 0x00004000; /* GPIOF[6] direction */ + gpio_ctl_writel(reg, 0x24); + + return was_protected; +} + +int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len) +{ + if (reg < arch_data.ahb_flash_base || + (reg + len) > (arch_data.ahb_flash_base + arch_data.ahb_flash_size)) + return -1; + reg -= arch_data.ahb_flash_base; + + if (((reg | (unsigned long)dst | len) & 3) == 0) { + while(len > 3) { + *(uint32_t *)dst = readl(arch_data.ahb_flash_map + reg); + dst += 4; + reg += 4; + len -= 4; + } + } + + while(len--) { + *(uint8_t *)dst = readb(arch_data.ahb_flash_map + reg++); + dst += 1; + } + return 0; +} + +static void close_devs(void) +{ + /* + * Old code doesn't do this, not sure why not + * + * munmap(arch_data.ahb_flash_map, arch_data.ahb_flash_size); + * munmap(arch_data.gpio_ctrl, GPIO_CTRL_SIZE); + * munmap(arch_data.ahb_reg_map, AHB_REGS_SIZE); + * close(arch_data.fd); + */ +} + +static int open_devs(enum flash_access access) +{ + if (access != BMC_DIRECT && access != PNOR_DIRECT) + return -1; + + arch_data.fd = open("/dev/mem", O_RDWR | O_SYNC); + if (arch_data.fd < 0) { + perror("can't open /dev/mem"); + return -1; + } + + arch_data.ahb_reg_map = mmap(0, AHB_REGS_SIZE, PROT_READ | PROT_WRITE, + MAP_SHARED, arch_data.fd, AHB_REGS_BASE); + if (arch_data.ahb_reg_map == MAP_FAILED) { + perror("can't map AHB registers /dev/mem"); + return -1; + } + arch_data.gpio_ctrl = mmap(0, GPIO_CTRL_SIZE, PROT_READ | PROT_WRITE, + MAP_SHARED, arch_data.fd, GPIO_CTRL_BASE); + if (arch_data.gpio_ctrl == MAP_FAILED) { + perror("can't map GPIO control via /dev/mem"); + return -1; + } + arch_data.ahb_flash_base = access == BMC_DIRECT ? BMC_FLASH_BASE : PNOR_FLASH_BASE; + arch_data.ahb_flash_size = access == BMC_DIRECT ? BMC_FLASH_SIZE : PNOR_FLASH_SIZE; + arch_data.ahb_flash_map = mmap(0, arch_data.ahb_flash_size, PROT_READ | + PROT_WRITE, MAP_SHARED, arch_data.fd, arch_data.ahb_flash_base); + if (arch_data.ahb_flash_map == MAP_FAILED) { + perror("can't map flash via /dev/mem"); + return -1; + } + return 0; +} + +static struct blocklevel_device *flash_setup(enum flash_access access) +{ + int rc; + struct blocklevel_device *bl; + struct spi_flash_ctrl *fl; + + if (access != BMC_DIRECT && access != PNOR_DIRECT) + return NULL; + + /* Open and map devices */ + rc = open_devs(access); + if (rc) + return NULL; + + /* Create the AST flash controller */ + rc = ast_sf_open(access == BMC_DIRECT ? AST_SF_TYPE_BMC : AST_SF_TYPE_PNOR, &fl); + if (rc) { + fprintf(stderr, "Failed to open controller\n"); + return NULL; + } + + /* Open flash chip */ + rc = flash_init(fl, &bl, &arch_data.flash_chip); + if (rc) { + fprintf(stderr, "Failed to open flash chip\n"); + return NULL; + } + + return bl; +} + +static bool is_bmc_part(const char *str) { + /* + * On AMI firmmware "fullpart" is what they called the BMC partition + * On OpenBMC "bmc" is what they called the BMC partition + */ + return strstr(str, "fullpart") || strstr(str, "bmc"); +} + +static bool is_pnor_part(const char *str) { + /* + * On AMI firmware "PNOR" is what they called the full PNOR + * On OpenBMC "pnor" is what they called the full PNOR + */ + return strcasestr(str, "pnor"); +} + +static char *get_dev_mtd(enum flash_access access) +{ + FILE *f; + char *ret = NULL, *pos = NULL; + char line[255]; + + if (access != BMC_MTD && access != PNOR_MTD) + return NULL; + + f = fopen("/proc/mtd", "r"); + if (!f) + return NULL; + + while (!pos && fgets(line, sizeof(line), f) != NULL) { + /* Going to have issues if we didn't get the full line */ + if (line[strlen(line) - 1] != '\n') + break; + + if (access == BMC_MTD && is_bmc_part(line)) { + pos = strchr(line, ':'); + if (!pos) + break; + + } else if (access == PNOR_MTD && is_pnor_part(line)) { + pos = strchr(line, ':'); + if (!pos) + break; + } + } + if (pos) { + *pos = '\0'; + if (asprintf(&ret, "/dev/%s", line) == -1) + ret = NULL; + } + + fclose(f); + return ret; +} + +enum flash_access arch_flash_access(struct blocklevel_device *bl, + enum flash_access access) +{ + if (access == ACCESS_INVAL) + return ACCESS_INVAL; + + if (!arch_data.init_bl) { + arch_data.access = access; + return access; + } + + /* Called with a BL not inited here, bail */ + if (arch_data.init_bl != bl) + return ACCESS_INVAL; + + return arch_data.flash_chip ? arch_data.access : ACCESS_INVAL; +} + +int arch_flash_erase_chip(struct blocklevel_device *bl) +{ + /* Called with a BL not inited here, bail */ + if (!arch_data.init_bl || arch_data.init_bl != bl) + return -1; + + if (!arch_data.flash_chip) { + /* Just assume its a regular erase */ + int rc; + uint64_t total_size; + + rc = blocklevel_get_info(bl, NULL, &total_size, NULL); + if (rc) + return rc; + + return blocklevel_erase(bl, 0, total_size); + } + + return flash_erase_chip(arch_data.flash_chip); +} + +int arch_flash_4b_mode(struct blocklevel_device *bl, int set_4b) +{ + /* Called with a BL not inited here, bail */ + if (!arch_data.init_bl || arch_data.init_bl != bl) + return -1; + + if (!arch_data.flash_chip) + return -1; + + return flash_force_4b_mode(arch_data.flash_chip, set_4b); +} + +int arch_flash_set_wrprotect(struct blocklevel_device *bl, int set) +{ + /* Called with a BL not inited here, bail */ + if (!arch_data.init_bl || arch_data.init_bl != bl) + return -1; + + if (arch_data.access == PNOR_MTD || arch_data.access == BMC_MTD) + return 0; /* Kernel looks after this for us */ + + if (!arch_data.flash_chip) + return -1; + + return set_wrprotect(set); +} + +int arch_flash_init(struct blocklevel_device **r_bl, const char *file, bool keep_alive) +{ + struct blocklevel_device *new_bl; + int rc = 0; + + /* Check we haven't already inited */ + if (arch_data.init_bl) + return -1; + + if (file) { + rc = file_init_path(file, NULL, keep_alive, &new_bl); + } else if (arch_data.access == BMC_MTD || arch_data.access == PNOR_MTD) { + char *mtd_dev; + + mtd_dev = get_dev_mtd(arch_data.access); + if (!mtd_dev) { + return -1; + } + rc = file_init_path(mtd_dev, NULL, keep_alive, &new_bl); + free(mtd_dev); + } else { + new_bl = flash_setup(arch_data.access); + if (!new_bl) + rc = -1; + } + if (rc) + return rc; + + arch_data.init_bl = new_bl; + *r_bl = new_bl; + return 0; +} + +void arch_flash_close(struct blocklevel_device *bl, const char *file) +{ + if (file || arch_data.access == BMC_MTD || arch_data.access == PNOR_MTD) { + file_exit_close(bl); + } else { + flash_exit_close(bl, &ast_sf_close); + close_devs(); + } +} diff --git a/roms/skiboot/external/common/arch_flash_arm_io.h b/roms/skiboot/external/common/arch_flash_arm_io.h new file mode 100644 index 000000000..85dbaf482 --- /dev/null +++ b/roms/skiboot/external/common/arch_flash_arm_io.h @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2015 IBM Corp. + */ +#ifndef __IO_H +#define __IO_H + +#include <assert.h> +#include <stdint.h> +#include <stdbool.h> + +#include <libflash/libflash.h> + +/* AST AHB register base */ +#define AHB_REGS_BASE 0x1E600000 +#define AHB_REGS_SIZE 0x00200000 + +/* AST GPIO control regs */ +#define GPIO_CTRL_BASE 0x1E780000 +#define GPIO_CTRL_SIZE 0x1000 + +/* AST AHB mapping of PNOR */ +#define PNOR_FLASH_BASE 0x30000000 +#define PNOR_FLASH_SIZE 0x04000000 + +/* AST AHB mapping of BMC flash */ +#define BMC_FLASH_BASE 0x20000000 +#define BMC_FLASH_SIZE 0x04000000 + +/* Address of flash mapping on LPC FW space */ +#define LPC_FLASH_BASE 0x0e000000 +#define LPC_CTRL_BASE 0x1e789000 + +static inline uint8_t readb(void *addr) +{ + asm volatile("" : : : "memory"); + return *(volatile uint8_t *)addr; +} + +static inline uint16_t readw(void *addr) +{ + asm volatile("" : : : "memory"); + return *(volatile uint16_t *)addr; +} + +static inline uint32_t readl(void *addr) +{ + asm volatile("" : : : "memory"); + return *(volatile uint32_t *)addr; +} + +static inline void writeb(uint8_t val, void *addr) +{ + asm volatile("" : : : "memory"); + *(volatile uint8_t *)addr = val; +} + +static inline void writew(uint16_t val, void *addr) +{ + asm volatile("" : : : "memory"); + *(volatile uint16_t *)addr = val; +} + +static inline void writel(uint32_t val, void *addr) +{ + asm volatile("" : : : "memory"); + *(volatile uint32_t *)addr = val; +} + +/* + * AHB register and flash access + */ + +extern uint32_t ast_ahb_readl(uint32_t offset); +extern void ast_ahb_writel(uint32_t val, uint32_t offset); +extern int ast_copy_to_ahb(uint32_t reg, const void *src, uint32_t len); +extern int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len); + +static inline void check_platform(bool *has_sfc, bool *has_ast) +{ + *has_sfc = false; + *has_ast = true; +} + +#endif /* __IO_H */ + diff --git a/roms/skiboot/external/common/arch_flash_common.c b/roms/skiboot/external/common/arch_flash_common.c new file mode 100644 index 000000000..c7a6e95ca --- /dev/null +++ b/roms/skiboot/external/common/arch_flash_common.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Default implementations + * + * Copyright 2015-2017 IBM Corp. + */ + +#include <stdlib.h> +#include <libflash/blocklevel.h> +#include "arch_flash.h" + +/* + * This just assumes that an erase from zero to total size is + * 'correct'. + * An erase from zero to total size is the correct approach for + * powerpc and x86. ARM has it own function which also includes a call + * to the flash driver. + */ +int __attribute__((weak)) arch_flash_erase_chip(struct blocklevel_device *bl) +{ + int rc; + uint64_t total_size; + + rc = blocklevel_get_info(bl, NULL, &total_size, NULL); + if (rc) + return rc; + + return blocklevel_erase(bl, 0, total_size); +} + +int __attribute__((weak,const)) arch_flash_4b_mode(struct blocklevel_device *bl, int set_4b) +{ + (void)bl; + (void)set_4b; + return -1; +} + +enum flash_access __attribute__((weak,const)) arch_flash_access(struct blocklevel_device *bl, enum flash_access access) +{ + (void)bl; + (void)access; + return ACCESS_INVAL; +} + +int __attribute__((weak,const)) arch_flash_set_wrprotect(struct blocklevel_device *bl, int set) +{ + (void)bl; + (void)set; + return -1; +} diff --git a/roms/skiboot/external/common/arch_flash_powerpc.c b/roms/skiboot/external/common/arch_flash_powerpc.c new file mode 100644 index 000000000..87661296d --- /dev/null +++ b/roms/skiboot/external/common/arch_flash_powerpc.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* Copyright 2013-2017 IBM Corp. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <unistd.h> +#include <dirent.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> + +#include <libflash/file.h> + +#include "arch_flash.h" + +#define FDT_FLASH_PATH "/proc/device-tree/chosen/ibm,system-flash" +#define SYSFS_MTD_PATH "/sys/class/mtd" + +static inline void hint_root(void) +{ + fprintf(stderr, "Do you have permission? Are you root?\n"); +} + +static int get_dev_attr(const char *dev, const char *attr_file, uint32_t *attr) +{ + char *dev_path = NULL; + int fd, rc; + + /* + * Needs to be large enough to hold at most uint32_t represented as a + * string in hex with leading 0x + */ + char attr_buf[10]; + + rc = asprintf(&dev_path, "%s/%s/%s", SYSFS_MTD_PATH, dev, attr_file); + if (rc < 0) { + dev_path = NULL; + goto out; + } + + fd = open(dev_path, O_RDONLY); + if (fd == -1) + goto out; + + rc = read(fd, attr_buf, sizeof(attr_buf)); + close(fd); + if (rc == -1) + goto out; + + if (attr) + *attr = strtol(attr_buf, NULL, 0); + + free(dev_path); + return 0; + +out: + free(dev_path); + fprintf(stderr, "Couldn't get MTD attribute '%s' from '%s'\n", dev, attr_file); + return -1; +} + +static int get_dev_mtd(const char *fdt_flash_path, char **mtd_path) +{ + struct dirent **namelist; + char fdt_node_path[PATH_MAX]; + int count, i, rc, fd; + bool done; + + if (!fdt_flash_path) + return -1; + + fd = open(fdt_flash_path, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Couldn't open '%s' FDT attribute to determine which flash device to use\n", + fdt_flash_path); + fprintf(stderr, "Is your skiboot new enough to expose the flash through the device tree?\n"); + hint_root(); + return -1; + } + + rc = read(fd, fdt_node_path, sizeof(fdt_node_path)); + close(fd); + if (rc == -1) { + fprintf(stderr, "Couldn't read flash FDT node from '%s'\n", fdt_flash_path); + hint_root(); + return -1; + } + + count = scandir(SYSFS_MTD_PATH, &namelist, NULL, alphasort); + if (count == -1) { + fprintf(stderr, "Couldn't scan '%s' for MTD\n", SYSFS_MTD_PATH); + hint_root(); + return -1; + } + + rc = 0; + done = false; + for (i = 0; i < count; i++) { + struct dirent *dirent; + char *dev_path; + char fdt_node_path_tmp[PATH_MAX]; + + dirent = namelist[i]; + + /* + * The call to asprintf must happen last as when it succeeds it + * will allocate dev_path + */ + if (dirent->d_name[0] == '.' || rc || done || + asprintf(&dev_path, "%s/%s/device/of_node", SYSFS_MTD_PATH, dirent->d_name) < 0) { + free(namelist[i]); + continue; + } + + rc = readlink(dev_path, fdt_node_path_tmp, sizeof(fdt_node_path_tmp) - 1); + free(dev_path); + if (rc == -1) { + /* + * This might fail because it could not exist if the system has flash + * devices that present as mtd but don't have corresponding FDT + * nodes, just continue silently. + */ + free(namelist[i]); + /* Should still try the next dir so reset rc */ + rc = 0; + continue; + } + fdt_node_path_tmp[rc] = '\0'; + + if (strstr(fdt_node_path_tmp, fdt_node_path)) { + uint32_t flags, size; + + /* + * size and flags could perhaps have be gotten another way but this + * method is super unlikely to fail so it will do. + */ + + /* Check to see if device is writeable */ + rc = get_dev_attr(dirent->d_name, "flags", &flags); + if (rc) { + free(namelist[i]); + continue; + } + + /* Get the size of the mtd device while we're at it */ + rc = get_dev_attr(dirent->d_name, "size", &size); + if (rc) { + free(namelist[i]); + continue; + } + + rc = asprintf(&dev_path, "/dev/%s", dirent->d_name); + if (rc < 0) { + free(namelist[i]); + continue; + } + rc = 0; + *mtd_path = dev_path; + done = true; + } + free(namelist[i]); + } + free(namelist); + + if (!done) { + fprintf(stderr, "Couldn't find '%s' corresponding MTD\n", fdt_flash_path); + fprintf(stderr, "Is your kernel new enough to expose MTD?\n"); + } + + /* explicit negative value so as to not return a libflash code */ + return done ? rc : -1; +} + +static struct blocklevel_device *arch_init_blocklevel(const char *file, bool keep_alive) +{ + int rc; + struct blocklevel_device *new_bl = NULL; + char *real_file = NULL; + + if (!file) { + rc = get_dev_mtd(FDT_FLASH_PATH, &real_file); + if (rc) + return NULL; + } + + rc = file_init_path(file ? file : real_file, NULL, keep_alive, &new_bl); + if (rc) + new_bl = NULL; + free(real_file); + return new_bl; +} + +/* Skiboot will worry about this for us */ +int __attribute__((const)) arch_flash_set_wrprotect(struct blocklevel_device *bl, int set) +{ + (void)bl; + (void)set; + + return 0; +} + +enum flash_access __attribute__((const)) arch_flash_access(struct blocklevel_device *bl, + enum flash_access access) +{ + (void)bl; + + if (access != PNOR_MTD) + return ACCESS_INVAL; + + return PNOR_MTD; +} + +int arch_flash_init(struct blocklevel_device **r_bl, const char *file, bool keep_alive) +{ + struct blocklevel_device *new_bl; + + /* + * In theory here we should check that something crazy wasn't + * passed to arch_flash_access() and refuse to init. + * However, arch_flash_access won't accept anything except + * PNOR_MTD, if they want something different then they should + * have checked with arch_flash_access() + */ + new_bl = arch_init_blocklevel(file, keep_alive); + if (!new_bl) + return -1; + + *r_bl = new_bl; + return 0; +} + +void arch_flash_close(struct blocklevel_device *bl, const char *file) +{ + (void)file; + + file_exit_close(bl); +} diff --git a/roms/skiboot/external/common/arch_flash_powerpc_io.h b/roms/skiboot/external/common/arch_flash_powerpc_io.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roms/skiboot/external/common/arch_flash_powerpc_io.h diff --git a/roms/skiboot/external/common/arch_flash_unknown.c b/roms/skiboot/external/common/arch_flash_unknown.c new file mode 100644 index 000000000..00a355600 --- /dev/null +++ b/roms/skiboot/external/common/arch_flash_unknown.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 +/* Copyright 2013-2017 IBM Corp. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <limits.h> +#include <unistd.h> +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> + +#include <libflash/file.h> + +#include "arch_flash.h" + +int arch_flash_init(struct blocklevel_device **r_bl, const char *file, bool keep_alive) +{ + int rc; + struct blocklevel_device *new_bl; + + /* Must have passed through a file to operate on */ + if (!file) { + fprintf(stderr, "Cannot operate without a file\n"); + return -1; + } + + rc = file_init_path(file, NULL, keep_alive, &new_bl); + if (rc) + return -1; + + *r_bl = new_bl; + return 0; +} + +void arch_flash_close(struct blocklevel_device *bl, const char *file) +{ + (void)file; + file_exit_close(bl); +} diff --git a/roms/skiboot/external/common/arch_flash_unknown_io.h b/roms/skiboot/external/common/arch_flash_unknown_io.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roms/skiboot/external/common/arch_flash_unknown_io.h diff --git a/roms/skiboot/external/common/get_arch.sh b/roms/skiboot/external/common/get_arch.sh new file mode 100755 index 000000000..682710fcb --- /dev/null +++ b/roms/skiboot/external/common/get_arch.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +echo "#if defined(__powerpc__) +echo -n ARCH_POWERPC +#elif defined(__arm__) +echo -n ARCH_ARM +#else +echo -n ARCH_UNKNOWN +#endif" | $1cpp | /bin/sh + diff --git a/roms/skiboot/external/common/rules.mk b/roms/skiboot/external/common/rules.mk new file mode 100644 index 000000000..7190813b8 --- /dev/null +++ b/roms/skiboot/external/common/rules.mk @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: Apache-2.0 + +CC ?= $(CROSS_COMPILE)gcc +LD ?= $(CROSS_COMPILE)ld +ARCH := $(shell $(GET_ARCH) "$(CROSS_COMPILE)") + +ifeq ($(ARCH),ARCH_ARM) +arch := arm +ARCH_FILES := arch_flash_common.c arch_flash_arm.c ast-sf-ctrl.c +else +ifeq ($(ARCH),ARCH_POWERPC) +arch := powerpc +ARCH_FILES := arch_flash_common.c arch_flash_powerpc.c +else +arch := unknown +ARCH_FILES := arch_flash_common.c arch_flash_unknown.c +endif +endif + +# Use make V=1 for a verbose build. +ifndef V + Q_CC= @echo ' CC ' $@; + Q_LINK= @echo ' LINK ' $@; + Q_LN= @echo ' LN ' $@; + Q_MKDIR=@echo ' MKDIR ' $@; +endif + + +.PHONY: links +links: libflash ccan common + +libflash: + $(Q_LN)ln -sf ../../libflash ./libflash + +ccan: + $(Q_LN)ln -sf ../../ccan ./ccan + +common: + $(Q_LN)ln -sf ../common ./common + +make_version.sh: + $(Q_LN)ln -sf ../../make_version.sh + +ARCH_SRC := $(addprefix common/,$(ARCH_FILES)) +ARCH_OBJS := $(addprefix common-,$(ARCH_FILES:.c=.o)) + +# Arch links are like this so we can have dependencies work (so that we don't +# run the rule when the links exist), pretty build output (knowing the target +# name) and a list of the files so we can clean them up. +ARCH_LINKS ?= common/ast-sf-ctrl.c common/ast.h common/io.h common/lpc.h + +arch_links: $(ARCH_LINKS) +common/ast.h : ../../include/ast.h | common + $(Q_LN)ln -sf ../../include/ast.h common/ast.h + +common/io.h : ../common/arch_flash_$(arch)_io.h | common + $(Q_LN)ln -sf arch_flash_$(arch)_io.h common/io.h + +common/ast-sf-ctrl.c : ../../hw/ast-bmc/ast-sf-ctrl.c | common + $(Q_LN)ln -sf ../../hw/ast-bmc/ast-sf-ctrl.c common/ast-sf-ctrl.c + +common/lpc.h: ../../include/lpc.h | common + $(Q_LN)ln -sf ../../include/lpc.h common/lpc.h + +.PHONY: arch_clean +arch_clean: + rm -rf $(ARCH_OBJS) $(ARCH_LINKS) + +$(ARCH_SRC): | common + +$(ARCH_OBJS): common-%.o: common/%.c $(ARCH_LINKS) + $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + +common-arch_flash.o: $(ARCH_OBJS) + $(Q_LD)$(LD) -r $(ARCH_OBJS) -o $@ + |