diff options
Diffstat (limited to 'roms/SLOF/rtas/flash')
| -rw-r--r-- | roms/SLOF/rtas/flash/block_lists.c | 275 | ||||
| -rw-r--r-- | roms/SLOF/rtas/flash/block_lists.h | 23 | ||||
| -rw-r--r-- | roms/SLOF/rtas/flash/tmpXXX.update-comments | 11 | 
3 files changed, 309 insertions, 0 deletions
diff --git a/roms/SLOF/rtas/flash/block_lists.c b/roms/SLOF/rtas/flash/block_lists.c new file mode 100644 index 00000000..e632fd0b --- /dev/null +++ b/roms/SLOF/rtas/flash/block_lists.c @@ -0,0 +1,275 @@ +/****************************************************************************** + * 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 <product.h> +#include <stdio.h> +#include "block_lists.h" + +unsigned char sig_org[] = FLASHFS_PLATFORM_MAGIC; + +/* this function is part of the crc_lib assembler code */ +unsigned long check_flash_image(unsigned long, unsigned long, unsigned long); + +/* this functions needs to be implemented by the board specific flash code + * the functions always get 32 bytes and needs to deal with the data */ +void write_flash(unsigned long, unsigned short *); + +int progress = 0; + +int +print_progress(void) +{ +	static int i = 3; +	switch (i--) { +	case 3: +		printf("\b|"); +		break; +	case 2: +		printf("\b/"); +		break; +	case 1: +		printf("\b-"); +		break; +	case 0: +		printf("\b\\"); +	default: +		i = 3; +	} +	return 0; +} + +void +print_hash(void) +{ +	printf("\b# "); +} + +void +print_writing(void) +{ +	int counter = 42; +	printf("\nWriting Flash: |"); +	while (counter--) +		printf(" "); +	printf("|"); +	counter = 41; +	while (counter--) +		printf("\b"); + +} + +int +get_block_list_version(unsigned char *data) +{ +	if (data[0] == 0x01) +		return 1; +	return 0; +} + +static long +get_image_size(unsigned long *data, unsigned long length) +{ +	long size = 0; +	unsigned long i; +	for (i = 0; i < length / 8; i += 2) { +		size += data[1 + i]; +	} +	return size; +} + +static long +get_image_size_v0(unsigned long *data) +{ +	unsigned long bl_size = data[0]; +	return get_image_size(data + 1, bl_size - 8); +} + +static long +get_image_size_v1(unsigned long *data) +{ +	unsigned long *bl_addr = data; +	unsigned long bl_size; +	unsigned long *next; +	long size = 0; +	while (bl_addr) { +		bl_size = bl_addr[0]; +		next = (unsigned long *) bl_addr[1]; +		bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL; +		size += get_image_size(bl_addr + 2, bl_size - 0x10); +		bl_addr = next; +	} +	return size; +} + +long +get_size(unsigned long *data, int version) +{ +	if (version == 1) +		return get_image_size_v1(data); +	return get_image_size_v0(data); +} + +static unsigned long +write_one_block(unsigned long *block, unsigned long length, +		unsigned long offset) +{ +	unsigned long block_addr = (unsigned long) block; +	unsigned long i = 0; +	static unsigned int hash; +	if (offset == 0) +		hash = 0; + +	for (i = 0; i < length; i += 32, offset += 32, block_addr += 32) { +		write_flash(offset, (unsigned short *) block_addr); +		if (offset % 10 == 0) { +			print_progress(); +		} +		if (offset > hash * progress) { +			print_hash(); +			hash++; +		} +	} + +	return offset; +} + +static unsigned long +write_one_list(unsigned long *bl, unsigned long length, unsigned long offset) +{ +	unsigned long i; +	// 0x10: /8 for pointer /2 it has to be done in steps of 2 +	for (i = 0; i < length / 0x10; i++) { +		offset = +		    write_one_block((unsigned long *) *bl, *(bl + 1), offset); +		bl += 2; +	} +	return offset; +} + +void +write_block_list(unsigned long *bl, int version) +{ +	unsigned long offset = 0; +	unsigned long *bl_addr = bl; +	unsigned long bl_size; +	unsigned long *next; + +	if (version == 0) { +		// -8 = removed header length +		write_one_list(bl + 1, *(bl) - 8, offset); +		return; +	} + +	while (bl_addr) { +		bl_size = bl_addr[0]; +		next = (unsigned long *) bl_addr[1]; +		bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL; +		// -0x10 = removed header length +		offset = write_one_list(bl_addr + 2, bl_size - 0x10, offset); +		bl_addr = next; +	} + +} + +static int +check_one_list(unsigned long *bl, unsigned long length, unsigned long crc) +{ +	unsigned long i; +	// 0x10: /8 for pointer /2 it has to be done in steps of 2 +	for (i = 0; i < length / 0x10; i++) { +		crc = check_flash_image((unsigned long) *bl, *(bl + 1), crc); +		bl += 2; +	} +	return crc; +} + +int +image_check_crc(unsigned long *bl, int version) +{ +	unsigned long *bl_addr = bl; +	unsigned long bl_size; +	unsigned long *next; +	unsigned long crc = 0; + +	if (version == 0) { +		// -8 = removed header length +		return check_one_list(bl + 1, *(bl) - 8, crc); +	} + +	while (bl_addr) { +		bl_size = bl_addr[0]; +		next = (unsigned long *) bl_addr[1]; +		bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL; +		// -0x10 = removed header length +		crc = check_one_list(bl_addr + 2, bl_size - 0x10, crc); +		bl_addr = next; +	} +	return crc; +} + +static int +check_platform_one_list(unsigned long *bl, unsigned long bytesec) +{ +	unsigned long pos = bytesec; +	unsigned char *sig_tmp, *sig; +	unsigned long size = 0; +	sig = sig_org; + +	while (size < bytesec) { +		size += bl[1]; + +		while (size > pos) {	// 32 == FLASHFS_PLATFORM_MAGIC length +			sig_tmp = (unsigned char *) (bl[0] + pos); +			if (*sig++ != *sig_tmp) +				return -1; +			if (*sig_tmp == '\0' || (pos == bytesec + 32)) { +				pos = bytesec + 32; +				break; +			} +			pos++; +		} +		if (pos == (bytesec + 32)) +			return 0; +		bl += 2; +	} +	return 0; +} + +int +check_platform(unsigned long *bl, unsigned int bytesec, int version) +{ +	unsigned long *bl_addr = bl; +	unsigned long bl_size; +	unsigned long *next; +	unsigned long *ptr; +	ptr = bl; + +	if (version == 0) { +		ptr += 1;	// -8 = removed header length +		return check_platform_one_list(ptr, bytesec); +	} +	while (bl_addr) { +		ptr = bl_addr + 2;	// -0x10 = removed header length +		bl_size = bl_addr[0]; +		next = (unsigned long *) bl_addr[1]; +		bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL; +		if ((bl_size - 0x10) == 0) { +			bl_addr = next; +			continue; +		} +		if (check_platform_one_list(ptr, bytesec) == 0) +			return 0; + +		bl_addr = next; +	} +	return -1; +} diff --git a/roms/SLOF/rtas/flash/block_lists.h b/roms/SLOF/rtas/flash/block_lists.h new file mode 100644 index 00000000..b24b6506 --- /dev/null +++ b/roms/SLOF/rtas/flash/block_lists.h @@ -0,0 +1,23 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +extern int progress; +extern unsigned char sig_org[]; + +int print_progress(void); +void print_hash(void); +int get_block_list_version(unsigned char *); +int image_check_crc(unsigned long *, int); +long get_size(unsigned long *, int); +void print_writing(void); +void write_block_list(unsigned long *, int); +int check_platform(unsigned long *, unsigned int, int); diff --git a/roms/SLOF/rtas/flash/tmpXXX.update-comments b/roms/SLOF/rtas/flash/tmpXXX.update-comments new file mode 100644 index 00000000..cd3d1376 --- /dev/null +++ b/roms/SLOF/rtas/flash/tmpXXX.update-comments @@ -0,0 +1,11 @@ +# ***************************************************************************** +# * 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 +# ****************************************************************************/  | 
