aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikunj A. Dadhania <nikunj@linux.vnet.ibm.com>2012-10-16 11:49:51 +0530
committerDavid Gibson <david@gibson.dropbear.id.au>2012-10-17 16:30:58 +1100
commit0ad10f26c94a86a0c9c3970e53f9a9f6a744055d (patch)
tree40b0d9d2ba55512071a9e713bd2db55b84a65ef6
parent7000cbc4e14aa891adbfdcc07b157e8c9ebb026c (diff)
downloadSLOF-qemu-slof-20121018.zip
SLOF-qemu-slof-20121018.tar.gz
SLOF-qemu-slof-20121018.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
-rw-r--r--board-qemu/config2
-rw-r--r--board-qemu/include/southbridge.h1
-rw-r--r--board-qemu/llfw/Makefile2
-rw-r--r--board-qemu/slof/Makefile1
-rw-r--r--board-qemu/slof/qemu-bootlist.fs14
-rw-r--r--board-qemu/slof/rtas-nvram.fs48
-rw-r--r--board-qemu/slof/tree.fs3
-rw-r--r--lib/libbases/libbases.code2
-rw-r--r--lib/libbootmsg/bootmsg_lvl.S5
-rw-r--r--lib/libhvcall/libhvcall.h14
-rw-r--r--lib/libnvram/libnvram.code10
-rw-r--r--lib/libnvram/libnvram.in1
-rw-r--r--lib/libnvram/nvram.c88
-rw-r--r--lib/libnvram/nvram.h3
-rw-r--r--llfw/nvramlog.S5
-rw-r--r--slof/fs/logging.fs6
16 files changed, 179 insertions, 26 deletions
diff --git a/board-qemu/config b/board-qemu/config
index 63976a0..a381f19 100644
--- a/board-qemu/config
+++ b/board-qemu/config
@@ -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
diff --git a/board-qemu/include/southbridge.h b/board-qemu/include/southbridge.h
index 3ca4e04..1cdb422 100644
--- a/board-qemu/include/southbridge.h
+++ b/board-qemu/include/southbridge.h
@@ -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
diff --git a/board-qemu/llfw/Makefile b/board-qemu/llfw/Makefile
index e40472c..89f17f8 100644
--- a/board-qemu/llfw/Makefile
+++ b/board-qemu/llfw/Makefile
@@ -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
diff --git a/board-qemu/slof/Makefile b/board-qemu/slof/Makefile
index 07d4916..036ad61 100644
--- a/board-qemu/slof/Makefile
+++ b/board-qemu/slof/Makefile
@@ -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
diff --git a/board-qemu/slof/qemu-bootlist.fs b/board-qemu/slof/qemu-bootlist.fs
index 6b52b97..0a1aaf3 100644
--- a/board-qemu/slof/qemu-bootlist.fs
+++ b/board-qemu/slof/qemu-bootlist.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
diff --git a/board-qemu/slof/rtas-nvram.fs b/board-qemu/slof/rtas-nvram.fs
new file mode 100644
index 0000000..fdebfb2
--- /dev/null
+++ b/board-qemu/slof/rtas-nvram.fs
@@ -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
diff --git a/board-qemu/slof/tree.fs b/board-qemu/slof/tree.fs
index 533fc95..d00f5af 100644
--- a/board-qemu/slof/tree.fs
+++ b/board-qemu/slof/tree.fs
@@ -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
diff --git a/lib/libbases/libbases.code b/lib/libbases/libbases.code
index 7dc941d..45312e2 100644
--- a/lib/libbases/libbases.code
+++ b/lib/libbases/libbases.code
@@ -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 )
diff --git a/lib/libbootmsg/bootmsg_lvl.S b/lib/libbootmsg/bootmsg_lvl.S
index 65cf0c3..2e4c135 100644
--- a/lib/libbootmsg/bootmsg_lvl.S
+++ b/lib/libbootmsg/bootmsg_lvl.S
@@ -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)
diff --git a/lib/libhvcall/libhvcall.h b/lib/libhvcall/libhvcall.h
index 302e2a3..6e418ba 100644
--- a/lib/libhvcall/libhvcall.h
+++ b/lib/libhvcall/libhvcall.h
@@ -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);
diff --git a/lib/libnvram/libnvram.code b/lib/libnvram/libnvram.code
index f1fd414..723941d 100644
--- a/lib/libnvram/libnvram.code
+++ b/lib/libnvram/libnvram.code
@@ -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
diff --git a/lib/libnvram/libnvram.in b/lib/libnvram/libnvram.in
index 33ab3bc..bbb20a8 100644
--- a/lib/libnvram/libnvram.in
+++ b/lib/libnvram/libnvram.in
@@ -39,3 +39,4 @@ cod(internal-add-env)
cod(internal-del-env)
cod(internal-set-env)
+cod(internal-nvram-init)
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;
}
diff --git a/lib/libnvram/nvram.h b/lib/libnvram/nvram.h
index 1324809..fa6bdd4 100644
--- a/lib/libnvram/nvram.h
+++ b/lib/libnvram/nvram.h
@@ -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);
diff --git a/llfw/nvramlog.S b/llfw/nvramlog.S
index be6bfd8..eb14c95 100644
--- a/llfw/nvramlog.S
+++ b/llfw/nvramlog.S
@@ -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)
diff --git a/slof/fs/logging.fs b/slof/fs/logging.fs
index 4a31b50..002c480 100644
--- a/slof/fs/logging.fs
+++ b/slof/fs/logging.fs
@@ -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
;