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:
Nikunj A. Dadhania 2012-10-16 11:49:51 +05:30 committed by David Gibson
parent 7000cbc4e1
commit 0ad10f26c9
16 changed files with 178 additions and 25 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 )

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -39,3 +39,4 @@ cod(internal-add-env)
cod(internal-del-env)
cod(internal-set-env)
cod(internal-nvram-init)

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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
;