diff options
author | Nikunj A. Dadhania <nikunj@linux.vnet.ibm.com> | 2012-10-16 11:49:51 +0530 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2012-10-17 16:30:58 +1100 |
commit | 0ad10f26c94a86a0c9c3970e53f9a9f6a744055d (patch) | |
tree | 40b0d9d2ba55512071a9e713bd2db55b84a65ef6 /lib/libnvram/nvram.c | |
parent | 7000cbc4e14aa891adbfdcc07b157e8c9ebb026c (diff) | |
download | SLOF-0ad10f26c94a86a0c9c3970e53f9a9f6a744055d.zip SLOF-0ad10f26c94a86a0c9c3970e53f9a9f6a744055d.tar.gz SLOF-0ad10f26c94a86a0c9c3970e53f9a9f6a744055d.tar.bz2 |
SLOF: Support PAPR NVRAM RTAS callsqemu-slof-20121018
BenH still need to ACK this though.
From: Nikunj A. Dadhania <nikunj@linux.vnet.ibm.com>
* Determines size of the flash using device tree.
* Provides nvram access functions for RTAS_NVRAM
* Allocates temporary buffer of nvram in SLOF code and use that in C.
(sbrk not available)
* NVRAM_LENGTH is used at various places, make sure it is well guarded
and also use dynamically determined size once an RTAS-NVRAM is
found.
* Use NVRAM_LENGTH as a variable in case of RTAS_NVRAM, not very
elegant though
Signed-off-by: Nikunj A. Dadhania <nikunj@linux.vnet.ibm.com>
--
Changelog from v1:
* #define cleanups suggested by Thomas/Benh
* Fix makefile which missed passing $FLAG for building llfw
* renamed vio-nvram.fs as rtas-nvram.fs
Diffstat (limited to 'lib/libnvram/nvram.c')
-rw-r--r-- | lib/libnvram/nvram.c | 88 |
1 files changed, 80 insertions, 8 deletions
diff --git a/lib/libnvram/nvram.c b/lib/libnvram/nvram.c index 048ec0f..2cb83dc 100644 --- a/lib/libnvram/nvram.c +++ b/lib/libnvram/nvram.c @@ -12,6 +12,7 @@ #include "cache.h" #include "nvram.h" +#include "../libhvcall/libhvcall.h" #include <stdio.h> #include <stdarg.h> @@ -20,9 +21,38 @@ #include <nvramlog.h> #include <byteorder.h> +#ifdef RTAS_NVRAM +static uint32_t fetch_token; +static uint32_t store_token; +static uint32_t NVRAM_LENGTH; +static char *nvram_buffer; /* use buffer allocated by SLOF code */ +#else #ifndef NVRAM_LENGTH #define NVRAM_LENGTH 0x10000 #endif +/* + * This is extremely ugly, but still better than implementing + * another sbrk() around it. + */ +static char nvram_buffer[NVRAM_LENGTH]; +#endif + +static uint8_t nvram_buffer_locked=0x00; + +void nvram_init(uint32_t _fetch_token, uint32_t _store_token, + long _nvram_length, void* nvram_addr) +{ +#ifdef RTAS_NVRAM + fetch_token = _fetch_token; + store_token = _store_token; + NVRAM_LENGTH = _nvram_length; + nvram_buffer = nvram_addr; + + printf("\nNVRAM: size=%d, fetch=%x, store=%x\n", + NVRAM_LENGTH, fetch_token, store_token); +#endif +} + void asm_cout(long Character,long UART,long NVRAM); @@ -48,6 +78,46 @@ static volatile uint8_t nvram[NVRAM_LENGTH]; /* FAKE */ *pos = data; \ } +#elif defined(RTAS_NVRAM) + +static inline void nvram_fetch(unsigned int offset, void *buf, unsigned int len) +{ + struct hv_rtas_call rtas = { + .token = fetch_token, + .nargs = 3, + .nrets = 2, + .argret = { offset, (uint32_t)(unsigned long)buf, len }, + }; + h_rtas(&rtas); +} + +static inline void nvram_store(unsigned int offset, void *buf, unsigned int len) +{ + struct hv_rtas_call rtas = { + .token = store_token, + .nargs = 3, + .nrets = 2, + .argret = { offset, (uint32_t)(unsigned long)buf, len }, + }; + h_rtas(&rtas); +} + +#define nvram_access(type,size,name) \ + type nvram_read_##name(unsigned int offset) \ + { \ + type val; \ + if (offset > (NVRAM_LENGTH - sizeof(type))) \ + return 0; \ + nvram_fetch(offset, &val, size / 8); \ + return val; \ + } \ + void nvram_write_##name(unsigned int offset, type data) \ + { \ + if (offset > (NVRAM_LENGTH - sizeof(type))) \ + return; \ + nvram_store(offset, &data, size / 8); \ + } + #else /* DISABLE_NVRAM */ static volatile uint8_t *nvram = (volatile uint8_t *)SB_NVRAM_adr; @@ -83,12 +153,7 @@ nvram_access(uint16_t, 16, word) nvram_access(uint32_t, 32, dword) nvram_access(uint64_t, 64, qword) -/* - * This is extremely ugly, but still better than implementing - * another sbrk() around it. - */ -static char nvram_buffer[NVRAM_LENGTH]; -static uint8_t nvram_buffer_locked=0x00; + /** * This function is a minimal abstraction for our temporary @@ -184,7 +249,7 @@ static char * get_partition_name(int offset) for (i=0; i<12; i++) name[i]=nvram_read_byte(offset+4+i); - // DEBUG("name: \"%s\"\n", name); + DEBUG("name: \"%s\"\n", name); return name; } @@ -217,7 +282,7 @@ static int calc_used_nvram_space(void) } len=get_partition_len(walk); - // DEBUG("... part len=%x, %x\n", len, len*16); + DEBUG("... part len=%x, %x\n", len, len*16); if(!len) { /* If there's a partition type but no len, bail out. @@ -546,6 +611,13 @@ void reset_nvram(void) void nvram_debug(void) { +#ifndef RTAS_NVRAM printf("\nNVRAM_BASE: %p\n", nvram); printf("NVRAM_LEN: 0x%x\n", NVRAM_LENGTH); +#endif +} + +unsigned int get_nvram_size(void) +{ + return NVRAM_LENGTH; } |