SLOF: Support PAPR NVRAM RTAS calls
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
This commit is contained in:
parent
7000cbc4e1
commit
0ad10f26c9
|
@ -1,6 +1,6 @@
|
|||
BOARD=qemu
|
||||
TARG=ppc64
|
||||
export FLAG="-DDISABLE_NVRAM"
|
||||
export FLAG=-DRTAS_NVRAM
|
||||
export CPUARCH=ppcp7
|
||||
export CPUARCHDEF=-DCPU_PPCP7
|
||||
#export SNK_BIOSEMU_APPS=1
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
/* Not used */
|
||||
#define SB_NVRAM_adr 0
|
||||
#define SB_FLASH_adr 0
|
||||
#define NVRAM_LENGTH 0x10000
|
||||
#define FLASH_LENGTH 0
|
||||
#define SB_MAILBOX_adr 0
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ include ../../make.rules
|
|||
|
||||
CPPFLAGS = -I$(INCLBRDDIR) -I$(INCLCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH) \
|
||||
-I$(LIBCMNDIR)/libc/include
|
||||
CFLAGS += -fno-builtin $(CPPFLAGS) -O2 -msoft-float $(MAMBO)
|
||||
CFLAGS += -fno-builtin $(FLAG) $(CPPFLAGS) -O2 -msoft-float $(MAMBO)
|
||||
CFLAGS += $(BOOT) $(IOCONF) -Wa,-mregnames $(RELEASE) $(CPUARCHDEF) -Wall
|
||||
ASFLAGS = $(BOOT) $(IOCONF) $(RELEASE)$(CPUARCHDEF) -Wa,-mregnames
|
||||
LDFLAGS1 = -nostdlib -e__start -Tstage2.lds -N -Ttext=0x100
|
||||
|
|
|
@ -63,6 +63,7 @@ VIO_FFS_FILES = \
|
|||
$(SLOFBRDDIR)/vio-vscsi.fs \
|
||||
$(SLOFBRDDIR)/vio-vscsi-device.fs \
|
||||
$(SLOFBRDDIR)/vio-veth.fs \
|
||||
$(SLOFBRDDIR)/rtas-nvram.fs \
|
||||
$(SLOFBRDDIR)/virtio-net.fs \
|
||||
$(SLOFBRDDIR)/virtio-block.fs \
|
||||
$(SLOFBRDDIR)/virtio-fs.fs
|
||||
|
|
|
@ -16,11 +16,15 @@ defer add-boot-device
|
|||
: qemu-read-bootlist ( -- )
|
||||
0 0 set-boot-device
|
||||
|
||||
\ check nvram
|
||||
" boot-device" evaluate swap drop 0 <> IF EXIT THEN
|
||||
|
||||
\ check qemu boot list
|
||||
" qemu,boot-device" get-chosen not IF EXIT THEN
|
||||
" qemu,boot-device" get-chosen not IF
|
||||
\ No boot list set from qemu, so check nvram
|
||||
" boot-device" evaluate swap drop 0= IF
|
||||
\ Not set in nvram too, set default disk/cdrom alias
|
||||
" disk" add-boot-device
|
||||
" cdrom" add-boot-device
|
||||
THEN
|
||||
EXIT
|
||||
THEN
|
||||
|
||||
0 ?DO
|
||||
dup i + c@ CASE
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
\ *****************************************************************************
|
||||
\ * Copyright (c) 2012 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
|
||||
\ ****************************************************************************/
|
||||
|
||||
." Populating " pwd cr
|
||||
|
||||
0 VALUE my-nvram-fetch
|
||||
0 VALUE my-nvram-store
|
||||
0 VALUE my-nvram-size
|
||||
0 VALUE nvram-addr
|
||||
|
||||
: open true ;
|
||||
: close ;
|
||||
|
||||
: write ( adr len -- actual )
|
||||
nip
|
||||
;
|
||||
|
||||
: read ( adr len -- actual )
|
||||
nip
|
||||
;
|
||||
|
||||
: setup-alias
|
||||
" nvram" find-alias 0= IF
|
||||
" nvram" get-node node>path set-alias
|
||||
ELSE
|
||||
drop
|
||||
THEN
|
||||
;
|
||||
|
||||
" #bytes" get-node get-package-property 0= IF
|
||||
decode-int to my-nvram-size 2drop
|
||||
" nvram-fetch" rtas-get-token to my-nvram-fetch
|
||||
" nvram-store" rtas-get-token to my-nvram-store
|
||||
my-nvram-size to nvram-size
|
||||
nvram-size alloc-mem to nvram-addr
|
||||
my-nvram-fetch my-nvram-store nvram-size nvram-addr internal-nvram-init
|
||||
THEN
|
||||
|
||||
setup-alias
|
|
@ -80,6 +80,9 @@ include fbuffer.fs
|
|||
2dup " IBM,l-lan" strequal IF
|
||||
" vio-veth.fs" included
|
||||
THEN
|
||||
2dup " qemu,spapr-nvram" strequal IF
|
||||
" rtas-nvram.fs" included
|
||||
THEN
|
||||
2drop
|
||||
THEN
|
||||
peer
|
||||
|
|
|
@ -20,7 +20,7 @@ MIRP
|
|||
// : get-nvram-size ( -- size )
|
||||
PRIM(get_X2d_nvram_X2d_size)
|
||||
PUSH;
|
||||
TOS.u = NVRAM_LENGTH;
|
||||
TOS.u = get_nvram_size();
|
||||
MIRP
|
||||
|
||||
// : get-flash-base ( -- base )
|
||||
|
|
|
@ -158,7 +158,8 @@ ENTRY(bootmsg_setlevel)
|
|||
andi. r3, r3, 0x7F
|
||||
add r6,r3,r6 // address |
|
||||
stb r4,0(r6) // store level |_ stwbrx r4,r3,r6
|
||||
#ifndef DISABLE_NVRAM
|
||||
|
||||
#if !defined(DISABLE_NVRAM) && !defined(RTAS_NVRAM)
|
||||
LOAD64(r6, SB_NVRAM_FWONLY_adr + 8 )
|
||||
add r6,r6,r3
|
||||
stb r4,0(r6)
|
||||
|
@ -167,7 +168,7 @@ ENTRY(bootmsg_setlevel)
|
|||
blr
|
||||
|
||||
ENTRY(bootmsg_nvupdate)
|
||||
#ifndef DISABLE_NVRAM
|
||||
#if !defined(DISABLE_NVRAM) && !defined(RTAS_NVRAM)
|
||||
mflr r10
|
||||
LOAD64(r3, SB_NVRAM_FWONLY_adr)
|
||||
lwz r4, 0(r3)
|
||||
|
|
|
@ -70,6 +70,20 @@ static inline long h_add_logical_lan_buffer(unsigned long unit_address,
|
|||
return hv_generic(H_ADD_LOGICAL_LAN_BUFFER, unit_address, buffer);
|
||||
}
|
||||
|
||||
#define HV_RTAS_MAX_ARGRET 5
|
||||
|
||||
struct hv_rtas_call {
|
||||
uint32_t token;
|
||||
uint32_t nargs;
|
||||
uint32_t nrets;
|
||||
uint32_t argret[HV_RTAS_MAX_ARGRET];
|
||||
};
|
||||
|
||||
static inline unsigned long h_rtas(struct hv_rtas_call *rtas_buf)
|
||||
{
|
||||
return hv_generic(KVMPPC_H_RTAS, (unsigned long)rtas_buf);
|
||||
}
|
||||
|
||||
extern unsigned long hv_logical_ci_load(unsigned long size, unsigned long addr);
|
||||
extern unsigned long hv_logical_ci_store(unsigned long size, unsigned long addr,
|
||||
unsigned long value);
|
||||
|
|
|
@ -276,4 +276,12 @@ PRIM(delete_X2d_nvram_X2d_partition)
|
|||
|
||||
MIRP
|
||||
|
||||
// ( fetch_token store_token size nvram-addr -- )
|
||||
PRIM(internal_X2d_nvram_X2d_init)
|
||||
void *nvram_addr = TOS.a; POP;
|
||||
uint32_t nvram_size = TOS.u; POP;
|
||||
uint32_t store_token = TOS.u; POP;
|
||||
long fetch_token = TOS.u; POP;
|
||||
|
||||
nvram_init(fetch_token, store_token, nvram_size, nvram_addr);
|
||||
MIRP
|
||||
|
|
|
@ -39,3 +39,4 @@ cod(internal-add-env)
|
|||
cod(internal-del-env)
|
||||
cod(internal-set-env)
|
||||
|
||||
cod(internal-nvram-init)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,9 @@ int delete_nvram_partition(partition_t part);
|
|||
void reset_nvram(void);
|
||||
void wipe_nvram(void);
|
||||
void nvram_debug(void);
|
||||
void nvram_init(uint32_t store_token, uint32_t fetch_token,
|
||||
long nv_size, void* nvram_addr);
|
||||
unsigned int get_nvram_size(void);
|
||||
|
||||
/* envvar.c */
|
||||
char *get_env(partition_t part, char *envvar);
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
#include <southbridge.h>
|
||||
#include <calculatecrc.h>
|
||||
|
||||
|
||||
#if !defined(DISABLE_NVRAM)
|
||||
#if !defined(DISABLE_NVRAM) && !defined(RTAS_NVRAM)
|
||||
|
||||
// detect overflow: if(a<b) return a else return 0
|
||||
#define NVRAM_LOG_DATA_OVERFLOW( a, b) \
|
||||
|
@ -342,7 +341,7 @@ ASM_ENTRY(.calPartitionHeaderChecksum)
|
|||
mr r4, r6
|
||||
blr
|
||||
|
||||
#else /* defined(DISABLE_NVRAM) */
|
||||
#else /* defined(DISABLE_NVRAM) || defined(RTAS_NVRAM) */
|
||||
|
||||
ASM_ENTRY(.writeNVRAMbyte)
|
||||
ENTRY(writeLogByte)
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
defer nvramlog-write-byte
|
||||
|
||||
: .nvramlog-write-byte ( byte -- )
|
||||
#ifndef DISABLE_NVRAM
|
||||
0 1 asm-cout
|
||||
#else
|
||||
#if defined(DISABLE_NVRAM) || defined(RTAS_NVRAM)
|
||||
drop
|
||||
#else
|
||||
0 1 asm-cout
|
||||
#endif
|
||||
;
|
||||
|
||||
|
|
Loading…
Reference in New Issue