diff options
Diffstat (limited to 'roms/SLOF/board-js2x/rtas')
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/Makefile | 89 | ||||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/i2c_bmc.oco | bin | 0 -> 22608 bytes | |||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/ipmi_oem.oco | bin | 0 -> 5432 bytes | |||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/rtas_board.c | 218 | ||||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/rtas_board.h | 45 | ||||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/rtas_flash.c | 614 | ||||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/rtas_flash.h | 20 | ||||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/rtas_i2c_bmc.h | 27 | ||||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/rtas_ipmi_bmc.h | 21 | ||||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/rtas_out.c | 120 | ||||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/rtas_pci.c | 116 | ||||
| -rw-r--r-- | roms/SLOF/board-js2x/rtas/rtas_table.c | 45 | 
12 files changed, 1315 insertions, 0 deletions
diff --git a/roms/SLOF/board-js2x/rtas/Makefile b/roms/SLOF/board-js2x/rtas/Makefile new file mode 100644 index 00000000..5ab5c34c --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/Makefile @@ -0,0 +1,89 @@ +# ***************************************************************************** +# * 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 ../Makefile.dirs + +include $(TOPBRDDIR)/config +include $(TOPCMNDIR)/make.rules + + +LDFLAGS		= -nostdlib +CPPFLAGS	= -I. -I$(LIBCMNDIR)/libc/include -I$(LIBCMNDIR)/libipmi -I$(INCLBRDDIR) \ +		  -I$(INCLCMNDIR) -I$(RTASCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH) +ASFLAGS		= -Wa,-mregnames $(FLAG) +CFLAGS		+= -Wall -Wextra -O2 -msoft-float -ffreestanding $(FLAG) + +# Board specific RTAS files: +BOARD_SRC_ASM	= +BOARD_SRC_C	= rtas_flash.c rtas_board.c rtas_pci.c  \ +		  rtas_out.c rtas_table.c  +BOARD_SRCS	= $(BOARD_SRC_ASM) $(BOARD_SRC_C) +BOARD_OBJ	= $(BOARD_SRC_ASM:%.S=%.o) $(BOARD_SRC_C:%.c=%.o) $(BOARD_OCO:%.oco=%.o) +BOARD_OCO	= i2c_bmc.oco ipmi_oem.oco + + +# Common RTAS files (from $(RTASCMNDIR) directory): +RTAS_SRC_ASM	= rtas_entry.S rtas_common.S reloc.S +RTAS_SRC_C	= rtas_call.c +RTAS_SRCS	= $(RTAS_SRC_ASM) $(RTAS_SRC_C) +RTAS_OBJ	= $(RTAS_SRC_ASM:%.S=%.o) $(RTAS_SRC_C:%.c=%.o) + +RTAS_FLASH_SRC  = block_lists.c +RTAS_FLASH_OBJ  = $(RTAS_FLASH_SRC:%.c=$(RTASCMNDIR)/flash/%.o) + +# Additional object files: +EXTRA_OBJ	= ../llfw/hw.o ../../lib/libc.a ../../lib/libipmi.a + +OBJS 		= $(RTAS_OBJ:%=$(RTASCMNDIR)/%) $(BOARD_OBJ) $(EXTRA_OBJ) \ +		  $(RTAS_FLASH_OBJ) + + +all:	Makefile.dep rtas.bin + +rtas.bin: rtas  +	$(OBJCOPY) -O binary $< $@ + +rtas: $(RTASCMNDIR)/rtas.lds $(OBJS) reloc_table.o  +	$(LD) $(LDFLAGS) -o $@ -T $(RTASCMNDIR)/rtas.lds $(OBJS) reloc_table.o + +reloc_table.o: $(TOOLSDIR)/gen_reloc_table $(OBJS) +	$(TOOLSDIR)/create_reloc_table.sh --ld "$(ONLY_LD)" --ldflags "$(LDFLAGS)" \ +	  --lds "$(RTASCMNDIR)/rtas.lds" --objcopy "$(OBJCOPY)" $(OBJS) + +$(TOOLSDIR)/gen_reloc_table: $(TOOLSDIR)/gen_reloc_table.c +	$(MAKE) -C $(TOOLSDIR) gen_reloc_table + +../../lib/libc.a: +	$(MAKE) -C ../../lib + +clean: +	$(MAKE) -C ../../lib clean +	rm -f $(OBJS) reloc_table.o rtas rtas.bin + +distclean : clean +	rm -f Makefile.dep + + +# Rules for creating the dependency file: +depend: +	$(CC) -MM $(CPPFLAGS) $(CFLAGS) $(BOARD_SRCS) > Makefile.dep +	$(CC) -MM $(CPPFLAGS) $(CFLAGS) $(RTAS_SRCS:%=$(RTASCMNDIR)/%) \ +	  | sed -e '/:/s,^,$(RTASCMNDIR)/,' >> Makefile.dep +Makefile.dep: +	$(MAKE) depend + +# Include dependency file if available: +ifneq (,$(wildcard Makefile.dep)) +include Makefile.dep +endif +%.o: %.oco +	cp -f $< $@ diff --git a/roms/SLOF/board-js2x/rtas/i2c_bmc.oco b/roms/SLOF/board-js2x/rtas/i2c_bmc.oco Binary files differnew file mode 100644 index 00000000..004e7f2e --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/i2c_bmc.oco diff --git a/roms/SLOF/board-js2x/rtas/ipmi_oem.oco b/roms/SLOF/board-js2x/rtas/ipmi_oem.oco Binary files differnew file mode 100644 index 00000000..ae401eaf --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/ipmi_oem.oco diff --git a/roms/SLOF/board-js2x/rtas/rtas_board.c b/roms/SLOF/board-js2x/rtas/rtas_board.c new file mode 100644 index 00000000..7f7409d9 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_board.c @@ -0,0 +1,218 @@ +/****************************************************************************** + * 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 <stdint.h> +#include <rtas.h> +#include "rtas_board.h" +#include <bmc.h> +#include <rtas_i2c_bmc.h> +#include <rtas_ipmi_bmc.h> +#include "libipmi.h" +#include <hw.h> + +void io_init(void); +short reg_get_flashside(void); +void rtas_init(void); + +typedef struct { +	uint64_t r3; +	uint64_t addr; +	volatile uint64_t id; +} slave_t; + +volatile slave_t rtas_slave_interface; + +static void +rtas_slave_loop(volatile slave_t * pIface) +{ +	uint64_t mask = pIface->id; +	pIface->id = 0; +	while (pIface->id != mask); { +		int dly = 0x1000; +		while (dly--); +	} +	pIface->id = 0; +	asm volatile ("  mr 3,%0 ; mtctr %1 ; bctr " +			::"r"(pIface->r3), "r"(pIface->addr)); +} + +void +rtas_fetch_slaves(rtas_args_t * pArgs) +{ +	int retVal = 0; +	int idx = 0; +	uint32_t mask = pArgs->args[0] & 0xFFFFFFFE; +	uint64_t *rtas_slave_loop_ptr = (uint64_t *)rtas_slave_loop; +	while (mask) { +		if (mask & 0x1) { +			rtas_slave_interface.id = idx | 0x100; +			*(int *) 0x3fc0 = (int)(unsigned long) &rtas_slave_interface;	// r3 +			*(int *) 0x3f80 = *rtas_slave_loop_ptr;		// addr +			*(int *) 0x3fa0 = idx | 0x100;	// pid +			while (rtas_slave_interface.id); +		} +		mask >>= 1; +		idx++; +	} +	pArgs->args[pArgs->nargs] = retVal; +} + +void +rtas_start_cpu(rtas_args_t * pArgs) +{ +	int retVal = 0; +	int idx = pArgs->args[0];	// pid +	rtas_slave_interface.r3 = pArgs->args[2];	// r3 +	rtas_slave_interface.addr = pArgs->args[1];	// addr +	asm(" sync "); +	rtas_slave_interface.id = idx | 0x100;	// pid +	while (rtas_slave_interface.id); +	pArgs->args[pArgs->nargs] = retVal; +} + +void +rtas_read_vpd(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = +	    bmc_read_vpd((uint8_t *) (uint64_t) pArgs->args[2], pArgs->args[1], +			 pArgs->args[0]); +} + +void +rtas_write_vpd(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = +	    bmc_write_vpd((uint8_t *) (uint64_t) pArgs->args[2], pArgs->args[1], +			  pArgs->args[0]); +} + +void +rtas_set_indicator(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_event_scan(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_stop_bootwatchdog(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = bmc_stop_bootwatchdog(); +} + +void +rtas_set_bootwatchdog(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = bmc_set_bootwatchdog(pArgs->args[0]); +} + +void +rtas_set_flashside(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = bmc_set_flashside(pArgs->args[0]); +} + +void +rtas_get_flashside(rtas_args_t * pArgs) +{ +	int retVal = bmc_get_flashside(); +	pArgs->args[pArgs->nargs] = retVal; +} + +void +rtas_flash_test(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_system_reboot(rtas_args_t * pArgs) +{ +	bmc_system_reboot(); +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_power_off(rtas_args_t * pArgs) +{ +	bmc_power_off(); +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_get_blade_descr(rtas_args_t * pArgs) +{ +	uint8_t *buffer = (uint8_t *) (uint64_t) pArgs->args[0]; +	uint32_t maxlen = pArgs->args[1]; +	uint32_t retlen = 0; +	uint32_t retval = bmc_get_blade_descr(buffer, maxlen, &retlen); +	pArgs->args[pArgs->nargs] = retlen; +	pArgs->args[pArgs->nargs + 1] = retval; +} + +// for JS20 cannot read blade descr +static uint32_t +dummy_get_blade_descr(uint8_t *dst, uint32_t maxlen, uint32_t *len) +{ +	// to not have a warning we need to do _something_ with *dst and maxlen... +	*dst = *dst; +	maxlen = maxlen; +	*len = 0; +	return -1; +} + +/* read flashside from register */ +short +reg_get_flashside(void) +{ +	short retVal; +	uint8_t val = load8_ci(0xf4003fe3); +	if (val & 0x80) { +		// temp +		retVal = 1; +	} else { +		// perm +		retVal = 0; +	} +	return retVal; +} + +void +rtas_init(void) +{ +	io_init(); +	if (u4Flag) { +		bmc_system_reboot = ipmi_system_reboot; +		bmc_power_off = ipmi_power_off; +		bmc_set_flashside = ipmi_set_flashside; +		bmc_get_flashside = reg_get_flashside; +		bmc_stop_bootwatchdog = ipmi_oem_stop_bootwatchdog; +		bmc_set_bootwatchdog = ipmi_oem_set_bootwatchdog; +		bmc_read_vpd = ipmi_oem_read_vpd; +		bmc_write_vpd = ipmi_oem_write_vpd; +		bmc_get_blade_descr = ipmi_oem_get_blade_descr; +	} else { +		bmc_system_reboot = i2c_system_reboot; +		bmc_power_off = i2c_power_off; +		bmc_set_flashside = i2c_set_flashside; +		bmc_get_flashside = i2c_get_flashside; +		bmc_stop_bootwatchdog = i2c_stop_bootwatchdog; +		bmc_set_bootwatchdog = i2c_set_bootwatchdog; +		bmc_read_vpd = i2c_read_vpd; +		bmc_write_vpd = i2c_write_vpd; +		bmc_get_blade_descr = dummy_get_blade_descr; +	} +} diff --git a/roms/SLOF/board-js2x/rtas/rtas_board.h b/roms/SLOF/board-js2x/rtas/rtas_board.h new file mode 100644 index 00000000..06766e14 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_board.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +#ifndef __RTAS_BOARD_H +#define __RTAS_BOARD_H + +#include <stddef.h> + +extern volatile unsigned char u4Flag; + +void rtas_ibm_read_pci_config(rtas_args_t * pArgs); +void rtas_ibm_write_pci_config(rtas_args_t * pArgs); +void rtas_read_pci_config(rtas_args_t * pArgs); +void rtas_write_pci_config(rtas_args_t * pArgs); +void rtas_system_reboot(rtas_args_t * pArgs); +void rtas_power_off(rtas_args_t * pArgs); +void rtas_display_character(rtas_args_t * pArgs); +void rtas_flash_test(rtas_args_t * pArgs); +void rtas_ibm_update_flash_64_and_reboot(rtas_args_t * pArgs); +void rtas_set_indicator(rtas_args_t * pArgs); +void rtas_event_scan(rtas_args_t * pArgs); +void rtas_ibm_manage_flash_image(rtas_args_t * pArgs); +void rtas_ibm_validate_flash_image(rtas_args_t * pArgs); +void rtas_update_flash(rtas_args_t * pArgs); +void rtas_set_flashside(rtas_args_t * pArgs); +void rtas_get_flashside(rtas_args_t * pArgs); +void rtas_dump_flash(rtas_args_t * pArgs); +void rtas_start_cpu(rtas_args_t * pArgs); +void rtas_read_vpd(rtas_args_t * pArgs); +void rtas_write_vpd(rtas_args_t * pArgs); +void rtas_fetch_slaves(rtas_args_t * pArgs); +void rtas_stop_bootwatchdog(rtas_args_t * pArgs); +void rtas_get_blade_descr(rtas_args_t * pArgs); +void rtas_set_bootwatchdog(rtas_args_t * pArgs); + +#endif				/* __RTAS_BOARD_H */ diff --git a/roms/SLOF/board-js2x/rtas/rtas_flash.c b/roms/SLOF/board-js2x/rtas/rtas_flash.c new file mode 100644 index 00000000..189878da --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_flash.c @@ -0,0 +1,614 @@ +/****************************************************************************** + * 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 <cpu.h> +#include <string.h> +#include <stdio.h> +#include <stdint.h> +#include <hw.h> +#include <rtas.h> +#include "rtas_board.h" +#include <bmc.h> +#include "rtas_flash.h" +#include <flash/block_lists.h> +#include "product.h" +#include "calculatecrc.h" + +#undef DEBUG + +#ifdef DEBUG +#define dprintf(_x ...) printf(_x) +#else +#define dprintf(_x ...) +#endif + +static uint64_t size; +static uint64_t flashOffset; + +unsigned char manage_flash_buffer[BUFSIZE*2]; +unsigned long check_flash_image(unsigned long rombase, unsigned long length, +				unsigned long start_crc); + +#ifdef DEBUG +static void +dump_blocklist(uint64_t *bl, int version) +{ +	uint64_t bl_size; +	uint8_t *addr = (uint8_t *)bl; + +	if (version == 1) { +		/* version 1 blocklist */ +		bl_size = *bl & 0x00FFFFFFFFFFFFFFUL; + +	} else { +		bl_size = *bl; +	} + +	printf("\n\rblocklist_dump %lx", bl_size); +	while (bl_size) { +		unsigned int tmpCnt = bl_size; +		unsigned char x; +		if (tmpCnt > 8) +			tmpCnt = 8; +		printf("\n\r%08x: ", addr); +		/* print hex */ +		while (tmpCnt--) { +			set_ci(); +			x = *addr++; +			clr_ci(); +			printf("%02x ", x); +		} +		tmpCnt = bl_size; +		if (tmpCnt > 8) +			tmpCnt = 8; +		bl_size -= tmpCnt; +		/* reset addr ptr to print ascii */ +		addr = addr - tmpCnt; +		/* print ascii */ +		while (tmpCnt--) { +			set_ci(); +			x = *addr++; +			clr_ci(); +			if ((x < 32) || (x >= 127)) { +				/* non-printable char */ +				x = '.'; +			} +			printf("%c", x); +		} +	} +	printf("\r\n"); +} +#endif + +void +rtas_dump_flash(rtas_args_t *rtas_args) +{ +	int retVal = 0; +	unsigned int size = rtas_args->args[0]; +	unsigned int offset = rtas_args->args[1]; +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; + +	printf("\n\rflash_dump %x %x", size, offset); +	flash += offset; +	while (size) { +		unsigned int tmpCnt = size; +		unsigned char x; +		if (tmpCnt > 16) +			tmpCnt = 16; +		printf("\n\r%p: ", flash); +		/* print hex */ +		while (tmpCnt--) { +			set_ci(); +			x = *flash++; +			clr_ci(); +			printf("%02x ", x); +		} +		tmpCnt = size; +		if (tmpCnt > 16) +			tmpCnt = 16; +		size -= tmpCnt; +		/* reset flash ptr to print ascii */ +		flash = flash - tmpCnt; +		/* print ascii */ +		while (tmpCnt--) { +			set_ci(); +			x = *flash++; +			clr_ci(); +			if ((x < 32) || (x >= 127)) { +				/* non-printable char */ +				x = '.'; +			} +			printf("%c", x); +		} +	} +	printf("\r\n"); +	rtas_args->args[rtas_args->nargs] = retVal; +} + + +static void +print_block(int i) +{ +	int counter = 8; + +	while (counter--) +		printf("\b"); +	printf("%08x", i); +} + + + +/* To enter data mode after flash has been in programming mode + * a 0xFF has to be written */ +static void +enter_data_mode(void) +{ +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; + +	set_ci(); +	*flash = 0xFF; +	eieio(); +	clr_ci(); +} + + +static void +erase_flash_block(unsigned long offset) +{ +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; + +	flash += offset; +	set_ci(); +	*flash = 0x20; +	eieio(); +	*flash = 0xd0; +	eieio(); +	while (!(*flash & 0x80)) ; +	clr_ci(); +} + + +void +write_flash(unsigned long offset, unsigned char *data) +{ +	int cnt = 32; +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; + +	flash += (offset + flashOffset); +	set_ci(); +	while (cnt) { +		if (!((uint64_t)flash & 0x1F)) { +			while (cnt) { +				uint64_t tmpcnt = cnt; +				if (tmpcnt > 0x20) +					tmpcnt = 0x20; +				do { +					*flash = 0xE8; +					eieio(); +				} while (!(*flash & 0x80)); +				cnt -= tmpcnt; +				*flash = tmpcnt - 1; +				while (tmpcnt--) { +					*flash++ = *data++; +				} +				*flash = 0xD0; +				eieio(); +				while (!(*flash & 0x80)) ; +			} +			break; +		} +		*flash = 0x40; +		eieio(); +		*flash++ = *data++; +		eieio(); +		while (!(*flash & 0x80)) ; +		cnt--; +	} +	clr_ci(); +} + +static void +write_flash_page(unsigned long offset, unsigned short *data) +{ +	int i = 0; + +	for (i = 0; i < BUFSIZE; i += 32, offset += 32) { +		write_flash(offset, ((unsigned char *)data + i)); +	} +} + +/* + * 0 reject temporary image + * 1 commit temporary image + * */ +static int +copy_flash(short mode) +{ +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; +	uint64_t blockCnt; +	uint64_t hash = 0; +	short notmode = mode ^ 0x1; + +	if (bmc_set_flashside(notmode) != notmode) { +		return -1; +	} +	printf("\r\nErasing Flash: 0x        "); + +	for (blockCnt = 0; blockCnt <= FLASHSIZE; blockCnt += FLASH_BLOCK_SIZE) { +		print_block(blockCnt); +		erase_flash_block(blockCnt); +	} +	enter_data_mode(); +	progress = FLASHSIZE / 38; +	print_writing(); + +	for (blockCnt = 0; blockCnt <= FLASHSIZE; blockCnt += BUFSIZE) { +		uint64_t *srcPtr = (uint64_t *)(flash + blockCnt); +		uint64_t *destPtr = (uint64_t *)manage_flash_buffer; +		uint64_t cnt = BUFSIZE / 8; +		if (bmc_set_flashside(mode) != mode) { +			return -1; +		} +		enter_data_mode(); +		set_ci(); +		while (cnt--) { +			*destPtr++ = *srcPtr++; +		} +		clr_ci(); + +		if (bmc_set_flashside(notmode) != notmode) { +			return -1; +		} +		write_flash_page(blockCnt, +				 (unsigned short *)manage_flash_buffer); + +		/* progress output... */ +		print_progress(); +		if (blockCnt > hash * progress) { +			print_hash(); +			hash++; +		} +	} +	enter_data_mode(); +	if (bmc_set_flashside(mode) != mode) { +		return -1; +	} +	printf("\b#\n"); +	return 0; +} + +/* + * Function: ibm_manage_flash_image + *	Input: + *		r3:   rtas parm structure + *			token:  46 + *			in:     1 + *			out:    1 + *			parm0:  0 reject temporary image + *				1 commit temporary image + *	Output: + *			parm1:  Status (hw -1, busy -2, parameter error -3 + *					-9001 cannot overwrite the active firmware image) + * + */ + +void +rtas_ibm_manage_flash_image(rtas_args_t *rtas_args) +{ +	int side; +	int result = 0; +	short mode = rtas_args->args[0]; + +	if (mode < 0 || mode > 1) { +		rtas_args->args[rtas_args->nargs] = -3; +		return; +	} +	side = bmc_get_flashside(); +	if (side == 0) { +		/* we are on the permanent side */ +		if (mode != 0) { +			rtas_args->args[rtas_args->nargs] = -9001; +			return; +		} +	} else if (side == 1) { +		/* we are on the temporary side */ +		if (mode != 1) { +			rtas_args->args[rtas_args->nargs] = -9001; +			return; +		} +	} else { +		rtas_args->args[rtas_args->nargs] = -1; +		return; +	} + +	result = copy_flash(mode); +	bmc_set_flashside(mode); +	enter_data_mode(); +	rtas_args->args[rtas_args->nargs] = result; +} + +/** + * check, if we find the FLASHFS_MAGIC token in bl + **/ +static uint8_t +check_magic(uint64_t *bl, int version) +{ +	struct stH *pHeader; + +	if (version == 1) { +		/* version 1 blocklist */ +		/* if block list size <= 0x10, it is only block list header */ +		/* and address of block list extension, so look at the extension... */ +		while ((*bl & 0x00FFFFFFFFFFFFFFUL) <= 0x10) +			bl = (uint64_t *)bl[1]; + +		/* block list item 2 _should_ be the address of our flashfs image */ +		pHeader = (struct stH *)(bl[2] + 0x28); +		/* printf("FlashFS Magic: \"%#s\"\r\n", pHeader->magic); */ +		return strncmp(pHeader->magic, FLASHFS_MAGIC, 8); +	} else { +		/* block list item 1 _should_ be the address of our flashfs image */ +		pHeader = (struct stH *)(bl[1] + 0x28); +		/* printf("FlashFS Magic: \"%#s\"\r\n", pHeader->magic); */ +		return strncmp(pHeader->magic, FLASHFS_MAGIC, 8); +	} +} + +static void +get_image_name(char *buffer, int maxsize) +{ +	volatile struct stH *flash_header = (volatile struct stH *)(SB_FLASH_adr + 0x28); +	/* since we cannot read the fh_magic directly from flash as a string, we need to copy it to memory */ +	uint64_t magic_val = 0; +	uint64_t addr; + +	/* copy fh_magic to magic_val since, we cannot use it as a string from flash */ +	magic_val = load64_ci((uint64_t)(flash_header->magic)); +	if (strncmp((char *)&magic_val, FLASHFS_MAGIC, 8)) { +		/* magic does not match */ +		sprintf(buffer, "Unknown"); +		buffer[maxsize - 1] = '\0'; +		return; +	} +	addr = (uint64_t)flash_header->version; +	while (--maxsize) { +		*buffer = load8_ci(addr++); +		if (!*buffer++) +			return; +	} +	*buffer = '\0'; +} + +/** + * validate_flash_image + * this function checks if the flash will be updated with the given image + * @param args[0] - buffer with minimum 4K of the image to flash + * @param args[1] - size of the buffer + * @param args[2] - status: + *                           0    success + *                          -1    hw + *                          -2    busy + *                          -3    parameter error + * @param args[3] - update result token + */ +void +rtas_ibm_validate_flash_image(rtas_args_t *rtas_args) +{ +	dprintf("\nrtas_ibm_validate_flash_image\n"); +	unsigned long new_image = rtas_args->args[0]; +	char *ret_str = (char *)new_image; +	struct stH *flash_header = (struct stH *)(new_image + 0x28); +	char current_temp_version[16]; +	char current_perm_version[16]; +	char new_version[16]; +	int side = bmc_get_flashside(); + +	/* fill args[0] with the current values which is needed +	 * in an error case */ + +	bmc_set_flashside(0); +	get_image_name(current_perm_version, sizeof(current_perm_version)); +	bmc_set_flashside(1); +	get_image_name(current_temp_version, sizeof(current_temp_version)); +	bmc_set_flashside(side); + +	/* check if the candidate image if valid for this platform */ +	if (strncmp(flash_header->magic, FLASHFS_MAGIC, 8)) { +		/* magic does not match */ +		rtas_args->args[rtas_args->nargs] = 0; +		/* No update done, the candidate image is +		 * not valid for this platform */ +		rtas_args->args[rtas_args->nargs + 1] = 2; +		sprintf(ret_str, "MI %s %s\xaMI %s %s", +			current_temp_version, current_perm_version, +			current_temp_version, current_perm_version); +		return; +	} + +	if (strncmp(flash_header->platform_name, (char *)sig_org, 32)) { +		/* this image if for a different board */ +		rtas_args->args[rtas_args->nargs] = 0; +		/* No update done, the candidate image is +		 * not valid for this platform */ +		rtas_args->args[rtas_args->nargs + 1] = 2; +		sprintf(ret_str, "MI %s %s\xaMI %s %s", +			current_temp_version, current_perm_version, +			current_temp_version, current_perm_version); +		return; +	} + +	/* check header crc */ +	if (check_flash_image(rtas_args->args[0], 0x88, 0)) { +		/* header crc failed */ +		rtas_args->args[rtas_args->nargs] = 0; +		/* No update done, the candidate image is +		 * not valid for this platform */ +		rtas_args->args[rtas_args->nargs + 1] = 2; +		sprintf(ret_str, "MI %s %s\xaMI %s %s", +			current_temp_version, current_perm_version, +			current_temp_version, current_perm_version); +		return; +	} +	memcpy(new_version, flash_header->version, 16); +	sprintf(ret_str, "MI %s %s\xaMI %s %s", current_temp_version, +		current_perm_version, new_version, current_perm_version); +	rtas_args->args[rtas_args->nargs] = 0; + +	if (strncmp(new_version, current_temp_version, 16) >= 0) +		rtas_args->args[rtas_args->nargs + 1] = 0; +	else +		rtas_args->args[rtas_args->nargs + 1] = 6; +} + +/* + * Function: ibm_update_flash_64 + *	Input: + *		r3:   rtas parm structure + *			token:  7 + *			in:     1 + *			out:    1 + *			parm0:  A real pointer to a block list + *	Output: + *			parm1:  Status (hw -1, bad image -3, programming failed -4) + * + *   Description: flash if addresses above 4GB have to be addressed + */ +void +rtas_update_flash(rtas_args_t *rtas_args) +{ +	void *bl = (void *)(uint64_t)rtas_args->args[0]; +	int version = get_block_list_version((unsigned char *)bl); +	uint64_t erase_size; +	unsigned int i; +	int perm_check = 1; + +#ifdef DEBUG +	dump_blocklist(bl, version); +#endif + +	/* from SLOF we pass a second (unofficial) parameter, if this parameter is 1, we do not +	 * check wether we are on permanent side. Needed for update-flash -c to work! */ +	if ((rtas_args->nargs > 1) && (rtas_args->args[1] == 1)) +		perm_check = 0; + +	/* check magic string */ +	printf("\r\nChecking magic string : "); +	if (check_magic(bl, version) != 0) { +		printf("failed!\n"); +		rtas_args->args[rtas_args->nargs] = -3; /* bad image */ +		return; +	} +	printf("succeeded!\n"); + +	/* check platform */ +	printf("Checking platform : "); +	if (check_platform(bl, 0x48, version) == -1) { +		printf("failed!\n"); +		rtas_args->args[rtas_args->nargs] = -3; /* bad image */ +		return; +	} +	printf("succeeded!\n"); + +	/* checkcrc */ +	printf("Checking CRC : "); +	/* the actual CRC is included at the end of the flash image, thus the resulting CRC must be 0! */ +	if (image_check_crc(bl, version) != 0) { +		printf("failed!\n"); +		rtas_args->args[1] = -3;        /* bad image */ +		return; +	} +	printf("succeeded!\n"); + +	/* check if we are running on P +	 * if so, let's switch to temp and flash temp */ +	if (bmc_get_flashside() == 0  && perm_check) { +		printf("Set flashside: "); +		bmc_set_flashside(1); +		printf("Temp!\n"); +	} + +#ifdef DEBUG +	rtas_args_t ra; +	ra.args[0] = 0x100;     /* size; */ +	ra.args[1] = flashOffset; +	ra.nargs = 2; + +	rtas_dump_flash(&ra); +	printf("\n"); +#endif + +	size = get_size(bl, version); +	erase_size = (size + (FLASH_BLOCK_SIZE - 1)) & ~(FLASH_BLOCK_SIZE - 1); +	dprintf("Erasing: size: %#x, erase_size: %#x, FLASH_BLOCK_SIZE: %#x\n", +		size, erase_size, FLASH_BLOCK_SIZE); + +	progress = size / 39; +	printf("Erasing : 0x%08x", 0); +	for (i = 0; i < erase_size; i += FLASH_BLOCK_SIZE) { +		print_block(i); +		erase_flash_block(i); +	} + +	enter_data_mode(); +#ifdef DEBUG +	rtas_dump_flash(&ra); +	printf("\n"); +#endif +	print_writing(); +	write_block_list(bl, version); +	printf("\b#\n"); +	enter_data_mode(); + +#ifdef DEBUG +	rtas_dump_flash(&ra); +	printf("\n"); +#endif + +	/* checkcrc */ +	printf("Recheck CRC : "); +	if (check_flash_image(FLASH + flashOffset, size, 0) != 0) { +		/* failed */ +		printf("failed!\n\r"); +		dprintf("flash_addr: %#x, flashOffset: %#x, size: %#x\n", FLASH, +			flashOffset, size); +		dprintf("crc: %#x\n", +			check_flash_image(FLASH + flashOffset, size, 0)); +		rtas_args->args[rtas_args->nargs] = -4; /* programming failed */ +		return; +	} +	printf("succeeded!\n"); +	rtas_args->args[rtas_args->nargs] = 0; +} + +/* + * Function: ibm_update_flash_64_and_reboot + *	Input: + *		r3:   rtas parm structure + *			token:  27 + *			in:     1 + *			out:    1 + *			parm0:  A real pointer to a block list + *	Output: + *			parm1:  Status (hw -1, bad image -3, programming failed -4) + *				Currently -4 and -1 are not returned + * + *  Description: flash and reboot if addresses above 4GB have to be addressed + */ +void +rtas_ibm_update_flash_64_and_reboot(rtas_args_t *rtas_args) +{ +	rtas_update_flash(rtas_args); +	dprintf("rc: %#d\n", rtas_args->args[rtas_args->nargs]); +	if (rtas_args->args[rtas_args->nargs] == 0) { +		rtas_system_reboot(rtas_args); +	} +} diff --git a/roms/SLOF/board-js2x/rtas/rtas_flash.h b/roms/SLOF/board-js2x/rtas/rtas_flash.h new file mode 100644 index 00000000..3eec45d2 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_flash.h @@ -0,0 +1,20 @@ +/****************************************************************************** + * 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 <southbridge.h> + +#define FLASHSIZE FLASH_LENGTH +#define FLASH SB_FLASH_adr +#define BUFSIZE 4096 +#define FLASH_BLOCK_SIZE 0x20000 + +void write_flash(unsigned long offset, unsigned char *data); diff --git a/roms/SLOF/board-js2x/rtas/rtas_i2c_bmc.h b/roms/SLOF/board-js2x/rtas/rtas_i2c_bmc.h new file mode 100644 index 00000000..e46de880 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_i2c_bmc.h @@ -0,0 +1,27 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +#ifndef __RTAS_I2C_BMC_H +#define __RTAS_I2C_BMC_H + +#include <stddef.h> + +void i2c_system_reboot (void); +void i2c_power_off (void); +short i2c_set_flashside (short mode); +short i2c_get_flashside (void); +int i2c_stop_bootwatchdog (void); +uint32_t i2c_read_vpd (uint8_t *dst, uint32_t len, uint32_t offset); +uint32_t i2c_write_vpd (uint8_t *src, uint32_t len, uint32_t offset); +int i2c_set_bootwatchdog(unsigned short seconds); + +#endif		/* __RTAS_I2C_BMC_H */ diff --git a/roms/SLOF/board-js2x/rtas/rtas_ipmi_bmc.h b/roms/SLOF/board-js2x/rtas/rtas_ipmi_bmc.h new file mode 100644 index 00000000..00532d4c --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_ipmi_bmc.h @@ -0,0 +1,21 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +#ifndef __RTAS_IPMI_BMC_H +#define __RTAS_IPMI_BMC_H + +#include <stddef.h> + +short ipmi_set_flashside (short mode); +short ipmi_get_flashside (void); + +#endif		/* __RTAS_IPMI_BMC_H */ diff --git a/roms/SLOF/board-js2x/rtas/rtas_out.c b/roms/SLOF/board-js2x/rtas/rtas_out.c new file mode 100644 index 00000000..ce4c00bd --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_out.c @@ -0,0 +1,120 @@ +/****************************************************************************** + * 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 <cpu.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <rtas.h> +#include <hw.h> +#include "rtas_board.h" + +volatile unsigned char *uart; +volatile unsigned char u4Flag; + +void io_init(void); +unsigned long check_flash_image(unsigned long rombase, unsigned long length, +				unsigned long start_crc); + +void +io_init(void) +{ +	// read ID register: only if it is a PC87427, enable serial2 +	store8_ci(0xf400002e, 0x20); +	if (load8_ci(0xf400002f) != 0xf2) { +		uart = (volatile unsigned char *) 0xf40003f8; +		u4Flag = 0; +	} else { +		uart = (volatile unsigned char *) 0xf40002f8; +		u4Flag = 1; +	} +} + +static void +display_char(char ch) +{ +	volatile int i = 0; +	volatile unsigned char *uart = (volatile unsigned char *) 0xf40002f8; +	int cnt = 2; +	while (cnt--) { +		set_ci(); +		while (!(uart[5] & 0x20)) { +			i++; +		} +		uart[0] = ch; +		clr_ci(); +		uart += 0x100; +	} +} + +ssize_t +write(int fd __attribute((unused)), const void *buf, size_t cnt) +{ +	while (cnt--) { +		display_char(*(char *) buf); +		if (*(char *) buf++ == '\n') +			display_char('\r'); +	} +	return 0; +} + +void * +sbrk(int incr __attribute((unused))) +{ +	return (void *) -1; +} + + + +void +rtas_display_character(rtas_args_t * pArgs) +{ +	int retVal = 0; +	display_char((char) pArgs->args[0]); +	pArgs->args[1] = retVal; +} + +unsigned long +check_flash_image(unsigned long rombase, unsigned long length, +		  unsigned long start_crc) +{ +	const uint32_t CrcTableHigh[16] = { +		0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90, +		0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7, +		0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E, +		0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09 +	}; +	const uint32_t CrcTableLow[16] = { +		0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, +		0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, +		0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, +		0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD +	}; + +	char *Buffer = (char *) rombase; +	uint32_t AccumCRC = start_crc; +	char val; +	uint32_t Temp; +	while (length-- > 0) { +		set_ci(); +		val = *Buffer; +		clr_ci(); +		Temp = ((AccumCRC >> 24) ^ val) & 0x000000ff; +		AccumCRC <<= 8; +		AccumCRC ^= CrcTableHigh[Temp / 16]; +		AccumCRC ^= CrcTableLow[Temp % 16]; +		++Buffer; +	} +	return AccumCRC; +} diff --git a/roms/SLOF/board-js2x/rtas/rtas_pci.c b/roms/SLOF/board-js2x/rtas/rtas_pci.c new file mode 100644 index 00000000..55dbf533 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_pci.c @@ -0,0 +1,116 @@ +/****************************************************************************** + * 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 <stdint.h> +#include <rtas.h> +#include <hw.h> +#include "rtas_board.h" + +void +rtas_ibm_read_pci_config (rtas_args_t *rtas_args) +{ +	int retVal = 0; +	uint64_t addr = ((uint64_t) rtas_args->args[1]) << 32;  // high 32 bits of PHB UID +	addr |= (rtas_args->args[2] & 0xFFFFFFFF); // low 32 bits of PHB UID +	addr |= (rtas_args->args[0] & 0x00FFFFFF); // bus, devfn, offset +	unsigned int size = rtas_args->args[3]; + +	/* Check for bus != 0  on PCI/PCI-X (PHB UID = 0xf2000000) */ +	if (((addr & 0xf2000000) == 0xf2000000) && (addr & 0xff0000)) +		addr += 0x1000000; + +	if (size == 1) +		rtas_args->args[5] = load8_ci(addr); +	else if (size == 2) +		rtas_args->args[5] = bswap16_load(addr); +	else if (size == 4) +		rtas_args->args[5] = bswap32_load(addr); +	else +		retVal = -3;  /* Bad arguments */ + +	rtas_args->args[4] = retVal; +} + +void +rtas_ibm_write_pci_config (rtas_args_t *rtas_args) +{ +	int retVal = 0; +	uint64_t addr = ((uint64_t) rtas_args->args[1]) << 32;  // high 32 bits of PHB UID +	addr |= (rtas_args->args[2] & 0xFFFFFFFF); // low 32 bits of PHB UID +	addr |= (rtas_args->args[0] & 0x00FFFFFF); // bus, devfn, offset +	unsigned int size = rtas_args->args[3]; + +	addr |= 0xf2000000; + +	/* Check for bus != 0  on PCI/PCI-X (PHB UID = 0xf2000000) */ +	if (((addr & 0xf2000000) == 0xf2000000) && (addr & 0xff0000)) +		addr += 0x1000000; + +	if (size == 1) +		store8_ci(addr, rtas_args->args[4]); +	else if (size == 2) +		bswap16_store(addr, rtas_args->args[4]); +	else if (size == 4) +		bswap32_store(addr, rtas_args->args[4]); +	else +		retVal = -3;  /* Bad arguments */ + +	rtas_args->args[5] = retVal; +} + +void +rtas_read_pci_config (rtas_args_t *rtas_args) +{ +	int retVal = 0; +	unsigned long addr = rtas_args->args[0]; +	unsigned int size = rtas_args->args[1]; +	addr |= 0xf2000000; + +	/* Check for bus != 0 */ +	if (addr & 0xff0000) +		addr += 0x1000000; + +	if (size == 1) +		rtas_args->args[3] = load8_ci(addr); +	else if (size == 2) +		rtas_args->args[3] = bswap16_load(addr); +	else if (size == 4) +		rtas_args->args[3] = bswap32_load(addr); +	else +		retVal = -3;  /* Bad arguments */ + +	rtas_args->args[2] = retVal; +} + +void +rtas_write_pci_config (rtas_args_t *rtas_args) +{ +	int retVal = 0; +	unsigned long addr = rtas_args->args[0]; +	unsigned int size = rtas_args->args[1]; + +	addr |= 0xf2000000; + +	/* Check for bus != 0 */ +	if (addr & 0xff0000) +		addr += 0x1000000; + +	if (size == 1) +		store8_ci(addr, rtas_args->args[2]); +	else if (size == 2) +		bswap16_store(addr, rtas_args->args[2]); +	else if (size == 4) +		bswap32_store(addr, rtas_args->args[2]); +	else +		retVal = -3;  /* Bad arguments */ + +	rtas_args->args[3] = retVal; +} diff --git a/roms/SLOF/board-js2x/rtas/rtas_table.c b/roms/SLOF/board-js2x/rtas/rtas_table.c new file mode 100644 index 00000000..fed4032a --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_table.c @@ -0,0 +1,45 @@ +/****************************************************************************** + * 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 <stdint.h> +#include <rtas.h> +#include "rtas_table.h" +#include "rtas_board.h" + +const rtas_funcdescr_t rtas_func_tab[] = { +	{"ibm,read-pci-config", rtas_ibm_read_pci_config, 0}, +	{"ibm,write-pci-config", rtas_ibm_write_pci_config, 0}, +	{"system-reboot", rtas_system_reboot, 0}, +	{"power-off", rtas_power_off, 0}, +	{"set-indicator", rtas_set_indicator, 0}, +	{"rtas-flash-test", rtas_flash_test, RTAS_TBLFLG_INTERNAL}, +	{"ibm,update-flash-64-and-reboot", rtas_ibm_update_flash_64_and_reboot, 0}, +	{"display-character", rtas_display_character, 0}, +	{"event-scan", rtas_event_scan, 0}, +	{"ibm,manage-flash-image", rtas_ibm_manage_flash_image, 0}, +	{"ibm,validate-flash-image", rtas_ibm_validate_flash_image, 0}, +	{"ibm,update-flash-64", rtas_update_flash, 0}, +	{"rtas-set-flashside", rtas_set_flashside, 0}, +	{"rtas-get-flashside", rtas_get_flashside, 0}, +	{"rtas-dump-flash", rtas_dump_flash, RTAS_TBLFLG_INTERNAL}, +	{"start-cpu", rtas_start_cpu, 0}, +	{"msg-read-vpd", rtas_read_vpd, RTAS_TBLFLG_INTERNAL}, +	{"msg-write-vpd", rtas_write_vpd, RTAS_TBLFLG_INTERNAL}, +	{"read-pci-config", rtas_read_pci_config, 0}, +	{"write-pci-config", rtas_write_pci_config, 0}, +	{"rtas-fetch-slaves", rtas_fetch_slaves, RTAS_TBLFLG_INTERNAL}, +	{"rtas-stop-bootwatchdog", rtas_stop_bootwatchdog, RTAS_TBLFLG_INTERNAL}, +	{"rtas-set-bootwatchdog", rtas_set_bootwatchdog, RTAS_TBLFLG_INTERNAL}, +	{"rtas-get-blade-descr", rtas_get_blade_descr, RTAS_TBLFLG_INTERNAL}, +}; + +const int rtas_func_tab_size = sizeof(rtas_func_tab) / sizeof(rtas_func_tab[0]);  | 
