/****************************************************************************** * Copyright (c) 2004, 2008 IBM Corporation * All rights reserved. * This program and the accompanying materials * are made available under the terms of the BSD License * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/bsd-license.php * * Contributors: * IBM Corporation - initial implementation *****************************************************************************/ #include "cache.h" #include "nvram.h" #include "../libhvcall/libhvcall.h" #include #include #include #include #include #include #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; DEBUG("\nNVRAM: size=%d, fetch=%x, store=%x\n", NVRAM_LENGTH, fetch_token, store_token); #endif } void asm_cout(long Character,long UART,long NVRAM); #if defined(DISABLE_NVRAM) static volatile uint8_t nvram[NVRAM_LENGTH]; /* FAKE */ #define nvram_access(type,size,name) \ type nvram_read_##name(unsigned int offset) \ { \ type *pos; \ if (offset > (NVRAM_LENGTH - sizeof(type))) \ return 0; \ pos = (type *)(nvram+offset); \ return *pos; \ } \ void nvram_write_##name(unsigned int offset, type data) \ { \ type *pos; \ if (offset > (NVRAM_LENGTH - sizeof(type))) \ return; \ pos = (type *)(nvram+offset); \ *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; #define nvram_access(type,size,name) \ type nvram_read_##name(unsigned int offset) \ { \ type *pos; \ if (offset > (NVRAM_LENGTH - sizeof(type))) \ return 0; \ pos = (type *)(nvram+offset); \ return ci_read_##size(pos); \ } \ void nvram_write_##name(unsigned int offset, type data) \ { \ type *pos; \ if (offset > (NVRAM_LENGTH - sizeof(type))) \ return; \ pos = (type *)(nvram+offset); \ ci_write_##size(pos, data); \ } #endif /* * producer for nvram access functions. Since these functions are * basically all the same except for the used data types, produce * them via the nvram_access macro to keep the code from bloating. */ nvram_access(uint8_t, 8, byte) nvram_access(uint16_t, 16, word) nvram_access(uint32_t, 32, dword) nvram_access(uint64_t, 64, qword) /** * This function is a minimal abstraction for our temporary * buffer. It should have been malloced, but since there is no * usable malloc, we go this route. * * @return pointer to temporary buffer */ char *get_nvram_buffer(int len) { if(len>NVRAM_LENGTH) return NULL; if(nvram_buffer_locked) return NULL; nvram_buffer_locked = 0xff; return nvram_buffer; } /** * @param buffer pointer to the allocated buffer. This * is unused, but nice in case we ever get a real malloc */ void free_nvram_buffer(char *buffer __attribute__((unused))) { nvram_buffer_locked = 0x00; } /** * @param fmt format string, like in printf * @param ... variable number of arguments */ int nvramlog_printf(const char* fmt, ...) { char buff[256]; int count, i; va_list ap; va_start(ap, fmt); count = vsprintf(buff, fmt, ap); va_end(ap); for (i=0; i>8)+(plainsum&0xff); return checksum; } static int calc_used_nvram_space(void) { int walk, len; for (walk=0; walk end_offset) { int j, bufferlen; char *overlap_buffer; bufferlen=free_offset - end_offset; overlap_buffer=get_nvram_buffer(bufferlen); if(!overlap_buffer) { return 0; } for (i=end_offset, j=0; i