From c9b6e84c9284e5283439135c226638b06ac05193 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 21 May 2015 09:12:50 +0200 Subject: initial support for pflash / cbfs Signed-off-by: Paolo Bonzini --- pflash.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 pflash.c (limited to 'pflash.c') diff --git a/pflash.c b/pflash.c new file mode 100644 index 0000000..950bc74 --- /dev/null +++ b/pflash.c @@ -0,0 +1,63 @@ +#include +#include "bios.h" +#include "pflash.h" +#include "stdio.h" + +#define CLEAR_STATUS_CMD 0x50 +#define READ_STATUS_CMD 0x70 +#define QUERY_CMD 0x98 +#define READ_ARRAY_CMD 0xff + +static void *pflash_detect(uint8_t *top_addr) +{ + volatile uint8_t *p = top_addr; + uint8_t save; + int i, blocks, sector_len; + + /* The low byte of the address is part of the command, so it must be 0. */ + if ((uintptr_t)p & 256) + panic(); + + p -= 256; + for (i = 0; i < 256; i++) + if (p[i] != CLEAR_STATUS_CMD) + break; + if (i == 256) + return NULL; + + save = p[i]; + p[i] = CLEAR_STATUS_CMD; + if (p[i] == CLEAR_STATUS_CMD) { + /* behaves as RAM */ + p[i] = save; + return NULL; + } + p[i] = READ_STATUS_CMD; + if (p[i] != 0) { + /* doesn't behave as flash */ + return NULL; + } + + /* 0x2d-0x2e: blocks_per_device - 1, little endian */ + /* 0x2f-0x30: sector_len / 256 */ + p[i] = QUERY_CMD; + blocks = p[0x2d] + (p[0x2e] << 8) + 1; + sector_len = (p[0x2f] + (p[0x30] << 8)) << 8; + + p[i] = READ_ARRAY_CMD; + return top_addr - blocks * sector_len; +} + +void *pflash_base(int n, size_t *size) +{ + uint8_t *top = NULL; + uint8_t *prev; + while (n-- >= 0) { + prev = top; + top = pflash_detect(top); + if (!top) + return NULL; + *size = prev - top; + } + return top; +} -- cgit v1.1