diff options
| author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-01-21 11:20:21 +0200 | 
|---|---|---|
| committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-01-21 11:20:21 +0200 | 
| commit | c6e4f26cc20a0a0986fd659cabde306f478a3575 (patch) | |
| tree | 79df92df7eab2d5152fdc421c91d41f40668559c /ubi-utils/sort-me-out | |
| parent | 8d7c0dd5c349f9bd57dad51c2492d3aaf2446a98 (diff) | |
ubi-utils: save original files in sort-me-out
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'ubi-utils/sort-me-out')
| -rw-r--r-- | ubi-utils/sort-me-out/list.c | 149 | ||||
| -rw-r--r-- | ubi-utils/sort-me-out/list.h | 56 | ||||
| -rw-r--r-- | ubi-utils/sort-me-out/peb.c | 116 | ||||
| -rw-r--r-- | ubi-utils/sort-me-out/peb.h | 41 | ||||
| -rw-r--r-- | ubi-utils/sort-me-out/pfi.c | 458 | ||||
| -rw-r--r-- | ubi-utils/sort-me-out/pfi.h | 244 | ||||
| -rw-r--r-- | ubi-utils/sort-me-out/pfiflash.h | 76 | ||||
| -rw-r--r-- | ubi-utils/sort-me-out/reader.c | 482 | ||||
| -rw-r--r-- | ubi-utils/sort-me-out/reader.h | 87 | 
9 files changed, 1709 insertions, 0 deletions
diff --git a/ubi-utils/sort-me-out/list.c b/ubi-utils/sort-me-out/list.c new file mode 100644 index 0000000..6eb716b --- /dev/null +++ b/ubi-utils/sort-me-out/list.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Oliver Lohmann + */ + +#include <stdlib.h> +#include <assert.h> +#include <stdio.h> + +#include "list.h" + +list_t +mk_empty(void) +{ +	return (list_t) NULL; +} + +int +is_empty(list_t l) +{ +	return l == NULL; +} + +info_t +head(list_t l) +{ +	assert(!is_empty(l)); +	return l->info; +} + +list_t +tail(list_t l) +{ +	assert(!is_empty(l)); +	return l->next; +} + +list_t +remove_head(list_t l) +{ +	list_t res; +	assert(!is_empty(l)); + +	res = l->next; +	free(l); +	return res; +} + +list_t +cons(info_t e, list_t l) +{ +	list_t res = malloc(sizeof(*l)); +	if (!res) +		return NULL; +	res->info = e; +	res->next = l; + +	return res; +} + +list_t +prepend_elem(info_t e, list_t l) +{ +	return cons(e,l); +} + +list_t +append_elem(info_t e, list_t l) +{ +	if (is_empty(l)) { +		return cons(e,l); +	} +	l->next = append_elem(e, l->next); + +	return l; +} + +list_t +insert_sorted(cmp_func_t cmp, info_t e, list_t l) +{ +	if (is_empty(l)) +		return cons(e, l); + +	switch (cmp(e, l->info)) { +	case -1: +	case  0: +		return l; +		break; +	case  1: +		l->next = insert_sorted(cmp, e, l); +		break; +	default: +		break; +	} + +	/* never reached */ +	return NULL; +} + +list_t +remove_all(free_func_t free_func, list_t l) +{ +	if (is_empty(l)) +		return l; +	list_t lnext = l->next; + +	if (free_func && l->info) { +		free_func(&(l->info)); +	} +	free(l); + +	return remove_all(free_func, lnext); +} + + +info_t +is_in(cmp_func_t cmp, info_t e, list_t l) +{ +	return +	(is_empty(l)) +	? NULL +	: (cmp(e, l->info)) == 0 ? l->info : is_in(cmp, e, l->next); +} + + +void +apply(process_func_t process_func, list_t l) +{ +	list_t ptr; +	void *i; +	foreach(i, ptr, l) { +		process_func(i); +	} +} diff --git a/ubi-utils/sort-me-out/list.h b/ubi-utils/sort-me-out/list.h new file mode 100644 index 0000000..e8452a2 --- /dev/null +++ b/ubi-utils/sort-me-out/list.h @@ -0,0 +1,56 @@ +#ifndef __LIST_H__ +#define __LIST_H__ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Oliver Lohmann + */ + +#include <stdint.h> + +#define foreach(elem, ptr, list)				\ +	for (elem = list != NULL ? (typeof(elem)) head(list)	\ +				 : NULL, ptr = list;		\ +		ptr != NULL;					\ +		ptr = tail(ptr),				\ +		elem = (typeof(elem)) ptr ? head(ptr) : NULL) + +typedef struct node* list_t; +typedef void* info_t; +typedef int  (*free_func_t)(info_t*); +typedef int  (*cmp_func_t)(info_t, info_t); +typedef void (*process_func_t)(info_t); + +struct node { +	list_t next; +	info_t	info; +}; + +list_t mk_empty(void); +int    is_empty(list_t l); +info_t is_in(cmp_func_t cmp, info_t e, list_t l); +info_t head(list_t l); +list_t tail(list_t l); +list_t remove_head(list_t l); +list_t cons(info_t e, list_t l); +list_t prepend_elem(info_t e, list_t); +list_t append_elem(info_t e, list_t); +list_t remove_all(free_func_t free_func, list_t l); +list_t insert_sorted(cmp_func_t cmp_func, info_t e, list_t l); +void   apply(process_func_t process_func, list_t l); + +#endif /* __LIST_H__ */ diff --git a/ubi-utils/sort-me-out/peb.c b/ubi-utils/sort-me-out/peb.c new file mode 100644 index 0000000..160a463 --- /dev/null +++ b/ubi-utils/sort-me-out/peb.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include "peb.h" + +int +peb_cmp(peb_t eb_1, peb_t eb_2) +{ +	assert(eb_1); +	assert(eb_2); + +	return eb_1->num == eb_2->num ? 0 +		: eb_1->num > eb_2->num ? 1 : -1; +} + +int +peb_new(uint32_t eb_num, uint32_t peb_size, peb_t *peb) +{ +	int rc = 0; + +	peb_t res = (peb_t) malloc(sizeof(struct peb)); +	if (!res) { +		rc = -ENOMEM; +		goto err; +	} + +	res->num  = eb_num; +	res->size = peb_size; +	res->data = (uint8_t*) malloc(res->size * sizeof(uint8_t)); +	if (!res->data) { +		rc = -ENOMEM; +		goto err; +	} +	memset(res->data, 0xff, res->size); + +	*peb = res; +	return 0; +err: +	if (res) { +		if (res->data) +			free(res->data); +		free(res); +	} +	*peb = NULL; +	return rc; +} + +int +peb_fill(peb_t peb, uint8_t* buf, size_t buf_size) +{ +	if (!peb) +		return -EINVAL; + +	if (buf_size > peb->size) +		return -EINVAL; + +	memcpy(peb->data, buf, buf_size); +	return 0; +} + +int +peb_write(FILE* fp_out, peb_t peb) +{ +	size_t written = 0; + +	if (peb == NULL) +		return -EINVAL; + +	written = fwrite(peb->data, 1, peb->size, fp_out); + +	if (written != peb->size) +		return -EIO; + +	return 0; +} + +int +peb_free(peb_t* peb) +{ +	peb_t tmp = *peb; +	if (tmp) { +		if (tmp->data) +			free(tmp->data); +		free(tmp); +	} +	*peb = NULL; + +	return 0; +} + +void peb_dump(FILE* fp_out, peb_t peb) +{ +	fprintf(fp_out, "num: %08d\tsize: 0x%08x\n", peb->num, peb->size); +} diff --git a/ubi-utils/sort-me-out/peb.h b/ubi-utils/sort-me-out/peb.h new file mode 100644 index 0000000..246bce8 --- /dev/null +++ b/ubi-utils/sort-me-out/peb.h @@ -0,0 +1,41 @@ +#ifndef __RAW_BLOCK_H__ +#define __RAW_BLOCK_H__ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Oliver Lohmann + */ + +#include <stdint.h> +#include <stdio.h> + +typedef struct peb *peb_t; +struct peb { +	uint32_t num;		/* Physical eraseblock number +				 * in the RAW file. */ +	uint32_t size;		/* Data Size (equals physical +				 * erase block size) */ +	uint8_t* data;		/* Data buffer */ +}; + +int  peb_new(uint32_t peb_num, uint32_t peb_size, peb_t* peb); +int  peb_free(peb_t* peb); +int  peb_cmp(peb_t peb_1, peb_t peb_2); +int  peb_write(FILE* fp_out, peb_t peb); +void peb_dump(FILE* fp_out, peb_t peb); + +#endif /* __RAW_BLOCK_H__ */ diff --git a/ubi-utils/sort-me-out/pfi.c b/ubi-utils/sort-me-out/pfi.c new file mode 100644 index 0000000..fa835e2 --- /dev/null +++ b/ubi-utils/sort-me-out/pfi.c @@ -0,0 +1,458 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * @file pfi.c + * + * @author Oliver Lohmann + *	   Andreas Arnez + *	   Joern Engel + *	   Frank Haverkamp + * + * @brief libpfi holds all code to create and process pfi files. + * + * <oliloh@de.ibm.com> Wed Feb	8 11:38:22 CET 2006: Initial creation. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <syslog.h> +#include <stdarg.h> +#include <errno.h> + +#include "pfi.h" + +#define PFI_MAGIC     "PFI!\n" +#define PFI_DATA      "DATA\n" /* The same size as PFI_MAGIC */ +#define PFI_MAGIC_LEN 5 + +static const char copyright [] __attribute__((unused)) = +	"Copyright (c) International Business Machines Corp., 2006"; + +enum key_id { +	/* version 1 */ +	key_version,	      /* must be index position 0! */ +	key_mode, +	key_size, +	key_crc, +	key_label, +	key_flags, +	key_ubi_ids, +	key_ubi_size, +	key_ubi_type, +	key_ubi_names, +	key_ubi_alignment, +	key_raw_starts, +	key_raw_total_size, +	num_keys, +}; + +struct pfi_header { +	char defined[num_keys];	 /* reserve all possible keys even if +				    version does not require this. */ +	int mode_no;		 /* current mode no. -> can only increase */ +	union { +		char *str; +		uint32_t num; +	} value[num_keys]; +}; + + +#define PFI_MANDATORY	    0x0001 +#define PFI_STRING	    0x0002 +#define PFI_LISTVALUE	    0x0004	/* comma seperated list of nums */ +#define PFI_MANDATORY_UBI   0x0008 +#define PFI_MANDATORY_RAW   0x0010 + +struct key_descriptor { +	enum key_id id; +	const char *name; +	uint32_t flags; +}; + +static const struct key_descriptor key_desc_v1[] = { +	{ key_version, "version", PFI_MANDATORY }, +	{ key_mode, "mode", PFI_MANDATORY | PFI_STRING }, +	{ key_size, "size", PFI_MANDATORY }, +	{ key_crc, "crc", PFI_MANDATORY }, +	{ key_label, "label", PFI_MANDATORY | PFI_STRING }, +	{ key_flags, "flags", PFI_MANDATORY }, +	{ key_ubi_ids, "ubi_ids", PFI_MANDATORY_UBI | PFI_STRING }, +	{ key_ubi_size, "ubi_size", PFI_MANDATORY_UBI }, +	{ key_ubi_type, "ubi_type", PFI_MANDATORY_UBI | PFI_STRING }, +	{ key_ubi_names, "ubi_names", PFI_MANDATORY_UBI | PFI_STRING }, +	{ key_ubi_alignment, "ubi_alignment", PFI_MANDATORY_UBI }, +	{ key_raw_starts, "raw_starts", PFI_MANDATORY_RAW | PFI_STRING }, +	{ key_raw_total_size, "raw_total_size", PFI_MANDATORY_RAW }, +}; + +static const struct key_descriptor *key_descriptors[] = { +	NULL, +	key_desc_v1,					   /* version 1 */ +}; + +static const int key_descriptors_max[] = { +	0,						   /* version 0 */ +	sizeof(key_desc_v1)/sizeof(struct key_descriptor), /* version 1 */ +}; + +#define ARRAY_SIZE(a)    (sizeof(a) / sizeof((a)[0])) + +static const char* modes[] = {"raw", "ubi"}; /* order isn't arbitrary! */ + +/* latest version contains all possible keys */ +static const struct key_descriptor *key_desc = key_desc_v1; + +#define PFI_IS_UBI(mode) \ +	(((mode) != NULL) && (strcmp("ubi", (mode)) == 0)) + +#define PFI_IS_RAW(mode) \ +	(((mode) != NULL) && (strcmp("raw", (mode)) == 0)) + +/** + * @return	 <0	On Error. + *		>=0	Mode no. + */ +static int +get_mode_no(const char* mode) +{ +	int i; + +	for (i = 0; i < (int)ARRAY_SIZE(modes); i++) +		if (strcmp(mode, modes[i]) == 0) +			return i; +	return -1; +} + +static int +find_key_by_name (const char *name) +{ +	int i; + +	for (i = 0; i < num_keys; i++) { +		if (strcmp(name, key_desc[i].name) == 0) +			return i; +	} +	return -1; +} + +static int +check_valid (pfi_header head) +{ +	int i; +	int max_keys; +	uint32_t version; +	const char *mode; +	const struct key_descriptor *desc; +	uint32_t to_check = PFI_MANDATORY; + +	/* +	 * For the validity check the list of possible keys depends on +	 * the version of the PFI file used. +	 */ +	version = head->value[key_version].num; +	if (version > PFI_HDRVERSION) +		return PFI_ENOHEADER; + +	max_keys = key_descriptors_max[version]; +	desc = key_descriptors[version]; + +	if (!desc) +		return PFI_ENOVERSION; + +	mode = head->value[key_mode].str; +	if (PFI_IS_UBI(mode)) { +		to_check |= PFI_MANDATORY_UBI; +	} +	else if (PFI_IS_RAW(mode)) { +		to_check |= PFI_MANDATORY_RAW; +	} +	else { /* neither UBI nor RAW == ERR */ +		return PFI_EINSUFF; +	} + +	for (i = 0; i < max_keys; i++) { +		if ((desc[i].flags & to_check) && !head->defined[i]) { +			fprintf(stderr, "libpfi: %s missing\n", desc[i].name); +			return PFI_EINSUFF; +		} +	} + +	return 0; +} + +int pfi_header_init (pfi_header *head) +{ +	int i; +	pfi_header self = (pfi_header) malloc(sizeof(*self)); + +	*head = self; +	if (self == NULL) +		return PFI_ENOMEM; + +	/* initialize maximum number of possible keys */ +	for (i = 0; i < num_keys; i++) { +		memset(self, 0, sizeof(*self)); +		self->defined[i] = 0; +	} + +	return 0; +} + +int pfi_header_destroy (pfi_header *head) +{ +	int i; +	pfi_header self = *head; + +	for (i = 0; i < num_keys; i++) { +		if (self->defined[i] && (key_desc[i].flags & PFI_STRING) && +		    self->value[i].str) { +			free(self->value[i].str); +		} +	} +	free(*head); +	*head = NULL; +	return 0; +} + +int pfi_header_setnumber (pfi_header head, +			   const char *key, uint32_t value) +{ +	int key_id = find_key_by_name(key); + +	if (key_id < 0) +		return PFI_EUNDEF; + +	if (key_desc[key_id].flags & PFI_STRING) +		return PFI_EBADTYPE; + +	head->value[key_id].num = value; +	head->defined[key_id] = 1; +	return 0; +} + +int pfi_header_setvalue (pfi_header head, +			  const char *key, const char *value) +{ +	int key_id = find_key_by_name(key); + +	if (value == NULL) +		return PFI_EINSUFF; + +	if ((key_id < 0) || (key_id >= num_keys)) +		return PFI_EUNDEF; + +	if (key_desc[key_id].flags & PFI_STRING) { +		/* +		 * The value is a string. Copy to a newly allocated +		 * buffer. Delete the old value, if already set. +		 */ +		size_t len = strlen(value) + 1; +		char *old_str = NULL; +		char *str; + +		old_str = head->value[key_id].str; +		if (old_str != NULL) +			free(old_str); + +		str = head->value[key_id].str = (char *) malloc(len); +		if (str == NULL) +			return PFI_ENOMEM; + +		strcpy(str, value); +	} else { +		int len; +		int ret; +		/* FIXME: here we assume that the value is always +		   given in hex and starts with '0x'. */ +		ret = sscanf(value, "0x%x%n", &head->value[key_id].num, &len); +		if (ret < 1 || value[len] != '\0') +			return PFI_EBADTYPE; +	} +	head->defined[key_id] = 1; +	return 0; +} + +int pfi_header_getnumber (pfi_header head, +			   const char *key, uint32_t *value) +{ +	int key_id = find_key_by_name(key); + +	if (key_id < 0) +		return PFI_EUNDEF; + +	if (key_desc[key_id].flags & PFI_STRING) +		return PFI_EBADTYPE; + +	if (!head->defined[key_id]) +		return PFI_EUNDEF; + +	*value = head->value[key_id].num; +	return 0; +} + +int pfi_header_getstring (pfi_header head, +			   const char *key, char *value, size_t size) +{ +	int key_id = find_key_by_name(key); + +	if (key_id < 0) +		return PFI_EUNDEF; + +	if (!(key_desc[key_id].flags & PFI_STRING)) +		return PFI_EBADTYPE; + +	if (!head->defined[key_id]) +		return PFI_EUNDEF; + +	strncpy(value, head->value[key_id].str, size-1); +	value[size-1] = '\0'; +	return 0; +} + +int pfi_header_write (FILE *out, pfi_header head) +{ +	int i; +	int ret; + +	pfi_header_setnumber(head, "version", PFI_HDRVERSION); + +	if ((ret = check_valid(head)) != 0) +		return ret; + +	/* OK.	Now write the header. */ + +	ret = fwrite(PFI_MAGIC, 1, PFI_MAGIC_LEN, out); +	if (ret < PFI_MAGIC_LEN) +		return ret; + + +	for (i = 0; i < num_keys; i++) { +		if (!head->defined[i]) +			continue; + +		ret = fprintf(out, "%s=", key_desc[i].name); +		if (ret < 0) +			return PFI_EFILE; + +		if (key_desc[i].flags & PFI_STRING) { +			ret = fprintf(out, "%s", head->value[i].str); +			if (ret < 0) +				return PFI_EFILE; +		} else { +			ret = fprintf(out, "0x%8x", head->value[i].num); +			if (ret < 0) +				return PFI_EFILE; + +		} +		ret = fprintf(out, "\n"); +		if (ret < 0) +			return PFI_EFILE; +	} +	ret = fprintf(out, "\n"); +	if (ret < 0) +		return PFI_EFILE; + +	ret = fflush(out); +	if (ret != 0) +		return PFI_EFILE; + +	return 0; +} + +int pfi_header_read (FILE *in, pfi_header head) +{ +	char magic[PFI_MAGIC_LEN]; +	char mode[PFI_KEYWORD_LEN]; +	char buf[256]; + +	if (PFI_MAGIC_LEN != fread(magic, 1, PFI_MAGIC_LEN, in)) +		return PFI_EFILE; +	if (memcmp(magic, PFI_MAGIC, PFI_MAGIC_LEN) != 0)  { +		if (memcmp(magic, PFI_DATA, PFI_MAGIC_LEN) == 0) { +			return PFI_DATA_START; +		} +		return PFI_ENOHEADER; +	} + +	while (fgets(buf, sizeof(buf), in) != NULL && buf[0] != '\n') { +		char *value; +		char *end; +		value = strchr(buf, '='); +		if (value == NULL) +			return PFI_ENOHEADER; + +		*value = '\0'; +		value++; +		end = strchr(value, '\n'); +		if (end) +		       *end = '\0'; + +		if (pfi_header_setvalue(head, buf, value)) +			return PFI_ENOHEADER; +	} + +	if (check_valid(head) != 0) +		return PFI_ENOHEADER; + +	/* set current mode no. in head */ +	pfi_header_getstring(head, "mode", mode, PFI_KEYWORD_LEN); +	if (head->mode_no > get_mode_no(mode)) { +		return PFI_EMODE; +	} +	head->mode_no = get_mode_no(mode); +	return 0; +} + +int pfi_header_dump (FILE *out, pfi_header head __attribute__((__unused__))) +{ +	fprintf(out, "Sorry not implemented yet. Write mail to " +		"Andreas Arnez and complain!\n"); +	return 0; +} + +int pfi_read (FILE *in, pfi_read_func func, void *priv_data) +{ +	int rc; +	pfi_header header; + +	rc = pfi_header_init (&header); +	if (0 != rc) +		return rc; +	if (!func) +		return PFI_EINVAL; + +	while ((0 == rc) && !feof(in)) { +		/* +		 * Read header and check consistency of the fields. +		 */ +		rc = pfi_header_read( in, header ); +		if (0 != rc) +			break; +		if (func) { +			rc = func(in, header, priv_data); +			if (rc != 0) +				break; +		} +	} + +	pfi_header_destroy(&header); +	return rc; +} diff --git a/ubi-utils/sort-me-out/pfi.h b/ubi-utils/sort-me-out/pfi.h new file mode 100644 index 0000000..8c5cc07 --- /dev/null +++ b/ubi-utils/sort-me-out/pfi.h @@ -0,0 +1,244 @@ +#ifndef __pfi_h +#define __pfi_h +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** + * @file pfi.h + * + * @author Oliver Lohmann <oliloh@de.ibm.com> + *         Andreas Arnez <arnez@de.ibm.com> + *         Joern Engel <engeljoe@de.ibm.com> + *         Frank Haverkamp <haverkam@de.ibm.com> + * + * @brief libpfi will hold all code to create and process pfi + * images. Definitions made in this file are equaly usable for the + * development host and the target system. + * + * @note This header additionally holds the official definitions for + * the pfi headers. + */ + +#include <stdio.h>		/* FILE */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Definitions. */ + +#define PFI_HDRVERSION 1	/* current header version */ + +#define PFI_ENOVERSION 1	/* unknown version */ +#define PFI_ENOHEADER  2	/* not a pfi header */ +#define PFI_EINSUFF    3	/* insufficient information */ +#define PFI_EUNDEF     4	/* key not defined */ +#define PFI_ENOMEM     5	/* out of memory */ +#define PFI_EBADTYPE   6	/* bad data type */ +#define PFI_EFILE      7	/* file I/O error: see errno */ +#define PFI_EFILEINVAL 8	/* file format not valid */ +#define PFI_EINVAL     9	/* invalid parameter */ +#define PFI_ERANGE     10	/* invalid range */ +#define PFI_EMODE      11	/* expecting other mode in this header */ +#define PFI_DATA_START 12	/* data section starts */ +#define PFI_EMAX       13	/* should be always larger as the largest +				   error code */ + +#define PFI_LABEL_LEN  64	/* This is the maximum length for a +				   PFI header label */ +#define PFI_KEYWORD_LEN 32	/* This is the maximum length for an +				   entry in the mode and type fields */ + +#define PFI_UBI_MAX_VOLUMES 128 +#define PFI_UBI_VOL_NAME_LEN 127 + +/** + * @brief The pfi header allows to set flags which influence the flashing + * behaviour. + */ +#define PFI_FLAG_PROTECTED   0x00000001 + + +/** + * @brief Handle to pfi header. Used in most of the functions associated + * with pfi file handling. + */ +typedef struct pfi_header *pfi_header; + + +/** + * @brief Initialize a pfi header object. + * + * @param head	 Pointer to handle. This function allocates memory + *		 for this data structure. + * @return	 0 on success, otherwise: + *		 PFI_ENOMEM : no memory available for the handle. + */ +int pfi_header_init (pfi_header *head); + + +/** + * @brief Destroy a pfi header object. + * + * @param head	 handle. head is invalid after calling this function. + * @return	 0 always. + */ +int pfi_header_destroy (pfi_header *head); + + +/** + * @brief Add a key/value pair to a pfi header object. + * + * @param head	 handle. + * @param key	 pointer to key string. Must be 0 terminated. + * @param value	 pointer to value string. Must be 0 terminated. + * @return	 0 on success, otherwise: + *		 PFI_EUNDEF   : key was not found. + *		 PFI_ENOMEM   : no memory available for the handle. + *		 PFI_EBADTYPE : value is not an hex string. This happens + *				 when the key stores an integer and the + *				 new value is not convertable e.g. not in + *				 0xXXXXXXXX format. + */ +int pfi_header_setvalue (pfi_header head, +			  const char *key, const char *value); + + +/** + * @brief Add a key/value pair to a pfi header object. Provide the + * value as a number. + * + * @param head	 handle. + * @param key	 pointer to key string. Must be 0 terminated. + * @param value	 value to set. + * @return	 0 on success, otherwise: + *		 PFI_EUNDEF   : key was not found. + *		 PFI_EBADTYPE : value is not a string. This happens + *				 when the key stores a string. + */ +int pfi_header_setnumber (pfi_header head, +			   const char *key, uint32_t value); + + +/** + * @brief For a given key, return the numerical value stored in a + * pfi header object. + * + * @param head	 handle. + * @param key	 pointer to key string. Must be 0 terminated. + * @param value	 pointer to value. + * @return	 0 on success, otherwise: + *		 PFI_EUNDEF   : key was not found. + *		 PFI_EBADTYPE : stored value is not an integer but a string. + */ +int pfi_header_getnumber (pfi_header head, +			   const char *key, uint32_t *value); + + +static inline uint32_t +pfi_getnumber(pfi_header head, const char *key) +{ +	uint32_t value; +	pfi_header_getnumber(head, key, &value); +	return value; +} + +/** + * @brief For a given key, return the string value stored in a pfi + * header object. + * + * @param head	 handle. + * @param key	 pointer to key string. Must be 0 terminated. + * @param value	 pointer to value string. Memory must be allocated by the user. + * @return	 0 on success, otherwise: + *		 PFI_EUNDEF   : key was not found. + *		 PFI_EBADTYPE : stored value is not a string but an integer. + */ +int pfi_header_getstring (pfi_header head, +			   const char *key, char *value, size_t size); + + +/** + * @brief Write a pfi header object into a given file. + * + * @param out	 output stream. + * @param head	 handle. + * @return	 0 on success, error values otherwise: + *		 PFI_EINSUFF   : not all mandatory fields are filled. + *		 PFI_ENOHEADER : wrong header version or magic number. + *		 -E*		: see <asm/errno.h>. + */ +int pfi_header_write (FILE *out, pfi_header head); + + +/** + * @brief Read a pfi header object from a given file. + * + * @param in	 input stream. + * @param head	 handle. + * @return	 0 on success, error values otherwise: + *		 PFI_ENOVERSION: unknown header version. + *		 PFI_EFILE     : cannot read enough data. + *		 PFI_ENOHEADER : wrong header version or magic number. + *		 -E*		: see <asm/errno.h>. + * + * If the header verification returned success the user can assume that + * all mandatory fields for a particular version are accessible. Checking + * the return code when calling the get-function for those keys is not + * required in those cases. For optional fields the checking must still be + * done. + */ +int pfi_header_read (FILE *in, pfi_header head); + + +/** + * @brief Display a pfi header in human-readable form. + * + * @param out	 output stream. + * @param head	 handle. + * @return	 always 0. + * + * @note Prints out that it is not implemented and whom you should + * contact if you need it urgently!. + */ +int pfi_header_dump (FILE *out, pfi_header head); + + +/* + * @brief	 Iterates over a stream of pfi files. The iterator function + *		 must advance the file pointer in FILE *in to the next pfi + *		 header. Function exists on feof(in). + * + * @param in	 input file descriptor, must be open and valid. + * @param func	 iterator function called when pfi header could be + *		 read and was validated. The function must return 0 on + *		 success. + * @return	 See pfi_header_init and pfi_header_read. + *		 PFI_EINVAL	  : func is not valid + *		 0 ok. + */ +typedef int (* pfi_read_func)(FILE *in, pfi_header hdr, void *priv_data); + +int pfi_read (FILE *in, pfi_read_func func, void *priv_data); + + +#ifdef __cplusplus +} +#endif + +#endif /* __pfi_h */ diff --git a/ubi-utils/sort-me-out/pfiflash.h b/ubi-utils/sort-me-out/pfiflash.h new file mode 100644 index 0000000..039705d --- /dev/null +++ b/ubi-utils/sort-me-out/pfiflash.h @@ -0,0 +1,76 @@ +#ifndef __PFIFLASH_H__ +#define __PFIFLASH_H__ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** + * + * @file pfi.h + * + * @author Oliver Lohmann <oliloh@de.ibm.com> + * + * @brief The pfiflash library offers an interface for using the + * pfiflash * utility. + */ + +#include <stdio.h>		/* FILE */ + +#define PFIFLASH_MAX_ERR_BUF_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum pdd_handling_t +{ +	PDD_KEEP = 0, +	PDD_MERGE, +	PDD_OVERWRITE, +	PDD_HANDLING_NUM, /* always the last item */ +} pdd_handling_t; /**< Possible PDD handle algorithms. */ + +/** + * @brief Flashes a PFI file to UBI Device 0. + * @param complete	[0|1] Do a complete system update. + * @param seqnum	Index in a redundant group. + * @param compare	[0|1] Compare contents. + * @param pdd_handling	The PDD handling algorithm. + * @param rawdev	Device to use for raw flashing + * @param err_buf	An error buffer. + * @param err_buf_size	Size of the error buffer. + */ +int pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare, +		pdd_handling_t pdd_handling, const char* rawdev, +		char *err_buf, size_t err_buf_size); + +/** + * @brief Flashes a PFI file to UBI Device 0. + * @param complete	[0|1] Do a complete system update. + * @param seqnum	Index in a redundant group. + * @param pdd_handling	The PDD handling algorithm. + * @param err_buf	An error buffer. + * @param err_buf_size	Size of the error buffer. + */ +int pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling, +		char *err_buf, size_t err_buf_size); + +#ifdef __cplusplus +} +#endif + +#endif /* __PFIFLASH_H__ */ diff --git a/ubi-utils/sort-me-out/reader.c b/ubi-utils/sort-me-out/reader.c new file mode 100644 index 0000000..0ea8c6d --- /dev/null +++ b/ubi-utils/sort-me-out/reader.c @@ -0,0 +1,482 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Oliver Lohmann + * + * Read in PFI (partial flash image) data and store it into internal + * data structures for further processing. Take also care about + * special handling if the data contains PDD (platform description + * data/boot-parameters). + */ + +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +#include "bootenv.h" +#include "reader.h" + +#define __unused __attribute__((unused)) + +/* @FIXME hard coded offsets right now - get them from Artem? */ +#define NAND2048_DEFAULT_VID_HDR_OFF 1984 +#define NAND512_DEFAULT_VID_HDR_OFF  448 +#define NOR_DEFAULT_VID_HDR_OFF      64 + +#define EBUF_PFI(fmt...)						\ +	do { int i = snprintf(err_buf, err_buf_size, "%s\n", label);	\ +	     snprintf(err_buf + i, err_buf_size - i, fmt);		\ +	} while (0) + +#define EBUF(fmt...) \ +	do { snprintf(err_buf, err_buf_size, fmt); } while (0) + + +int +read_pdd_data(FILE* fp_pdd, pdd_data_t* pdd_data, +	      char* err_buf, size_t err_buf_size) +{ +	int rc = 0; +	bootenv_t pdd = NULL; +	pdd_data_t res = NULL; +	const char* value; + +	res = (pdd_data_t) malloc(sizeof(struct pdd_data)); +	if (!res) { +		rc = -ENOMEM; +		goto err; +	} +	rc = bootenv_create(&pdd); +	if (rc != 0) { +		goto err; +	} +	rc = bootenv_read_txt(fp_pdd, pdd); +	if (rc != 0) { +		goto err; +	} +	rc = bootenv_get(pdd, "flash_type", &value); +	if (rc != 0) { +		goto err; +	} + +	if (strcmp(value, "NAND") == 0) { + +		rc = bootenv_get_num(pdd, "flash_page_size", +			     &(res->flash_page_size)); +		if (rc != 0) { +			EBUF("Cannot read 'flash_page_size' from pdd."); +			goto err; +		} +		res->flash_type = NAND_FLASH; + +		switch (res->flash_page_size) { +		case 512: +			res->vid_hdr_offset = NAND512_DEFAULT_VID_HDR_OFF; +			break; +		case 2048: +			res->vid_hdr_offset = NAND2048_DEFAULT_VID_HDR_OFF; +			break; +		default: +			EBUF("Unsupported  'flash_page_size' %d.", +			     res->flash_page_size); +			goto err; +		} +	} +	else if (strcmp(value, "NOR") == 0){ +		res->flash_type = NOR_FLASH; +		res->vid_hdr_offset = NOR_DEFAULT_VID_HDR_OFF; +	} +	else { +		snprintf(err_buf, err_buf_size, +			 "Unkown flash type: %s", value); +		goto err; +	} + +	rc = bootenv_get_num(pdd, "flash_eraseblock_size", +			     &(res->eb_size)); +	if (rc != 0) { +		EBUF("Cannot read 'flash_eraseblock_size' from pdd."); +		goto err; +	} + +	rc = bootenv_get_num(pdd, "flash_size", +			     &(res->flash_size)); +	if (rc != 0) { +		EBUF("Cannot read 'flash_size' from pdd."); +		goto err; +	} + +	goto out; + err: +	if (res) { +		free(res); +		res = NULL; +	} + out: +	bootenv_destroy(&pdd); +	*pdd_data = res; +	return rc; +} + +int +read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_raw_t* pfi_raw, +	     const char* label, char* err_buf, size_t err_buf_size) +{ +	int rc = 0; +	char tmp_str[PFI_KEYWORD_LEN]; +	bootenv_list_t raw_start_list = NULL; +	pfi_raw_t res; +	size_t size; + +	res = (pfi_raw_t) malloc(sizeof(struct pfi_raw)); +	if (!res) +		return -ENOMEM; + +	rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size)); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'size' from PFI."); +		goto err; +	} + +	rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc)); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'crc' from PFI."); +		goto err; +	} + +	rc = pfi_header_getstring(pfi_hd, "raw_starts", +				  tmp_str, PFI_KEYWORD_LEN); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'raw_starts' from PFI."); +		goto err; +	} + +	rc = bootenv_list_create(&raw_start_list); +	if (rc != 0) { +		goto err; +	} + +	rc = bootenv_list_import(raw_start_list, tmp_str); +	if (rc != 0) { +		EBUF_PFI("Cannot translate PFI value: %s", tmp_str); +		goto err; +	} + +	rc = bootenv_list_to_num_vector(raw_start_list, +					&size, &(res->starts)); +	res->starts_size = size; + +	if (rc != 0) { +		EBUF_PFI("Cannot create numeric value array: %s", tmp_str); +		goto err; +	} + +	goto out; + + err: +	if (res) { +		free(res); +		res = NULL; +	} + out: +	bootenv_list_destroy(&raw_start_list); +	*pfi_raw = res; +	return rc; +} + +int +read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi, +	     const char *label, char* err_buf, size_t err_buf_size) +{ +	int rc = 0; +	const char** tmp_names = NULL; +	char tmp_str[PFI_KEYWORD_LEN]; +	bootenv_list_t ubi_id_list = NULL; +	bootenv_list_t ubi_name_list = NULL; +	pfi_ubi_t res; +	uint32_t i; +	size_t size; + +	res = (pfi_ubi_t) calloc(1, sizeof(struct pfi_ubi)); +	if (!res) +		return -ENOMEM; + +	rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size)); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'size' from PFI."); +		goto err; +	} + +	rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc)); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'crc' from PFI."); +		goto err; +	} + +	rc = pfi_header_getstring(pfi_hd, "ubi_ids", tmp_str, PFI_KEYWORD_LEN); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'ubi_ids' from PFI."); +		goto err; +	} + +	rc = bootenv_list_create(&ubi_id_list); +	if (rc != 0) { +		goto err; +	} +	rc = bootenv_list_create(&ubi_name_list); +	if (rc != 0) { +		goto err; +	} + +	rc = bootenv_list_import(ubi_id_list, tmp_str); +	if (rc != 0) { +		EBUF_PFI("Cannot translate PFI value: %s", tmp_str); +		goto err; +	} + +	rc = bootenv_list_to_num_vector(ubi_id_list, &size, +					&(res->ids)); +	res->ids_size = size; +	if (rc != 0) { +		EBUF_PFI("Cannot create numeric value array: %s", tmp_str); +		goto err; +	} + +	if (res->ids_size == 0) { +		rc = -1; +		EBUF_PFI("Sanity check failed: No ubi_ids specified."); +		goto err; +	} + +	rc = pfi_header_getstring(pfi_hd, "ubi_type", +				  tmp_str, PFI_KEYWORD_LEN); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'ubi_type' from PFI."); +		goto err; +	} +	if (strcmp(tmp_str, "static") == 0) +		res->type = pfi_ubi_static; +	else if (strcmp(tmp_str, "dynamic") == 0) +		res->type = pfi_ubi_dynamic; +	else { +		EBUF_PFI("Unknown ubi_type in PFI."); +		goto err; +	} + +	rc = pfi_header_getnumber(pfi_hd, "ubi_alignment", &(res->alignment)); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'ubi_alignment' from PFI."); +		goto err; +	} + +	rc = pfi_header_getnumber(pfi_hd, "ubi_size", &(res->size)); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'ubi_size' from PFI."); +		goto err; +	} + +	rc = pfi_header_getstring(pfi_hd, "ubi_names", +				  tmp_str, PFI_KEYWORD_LEN); +	if (rc != 0) { +		EBUF_PFI("Cannot read 'ubi_names' from PFI."); +		goto err; +	} + +	rc = bootenv_list_import(ubi_name_list, tmp_str); +	if (rc != 0) { +		EBUF_PFI("Cannot translate PFI value: %s", tmp_str); +		goto err; +	} +	rc = bootenv_list_to_vector(ubi_name_list, &size, +				    &(tmp_names)); +	res->names_size = size; +	if (rc != 0) { +		EBUF_PFI("Cannot create string array: %s", tmp_str); +		goto err; +	} + +	if (res->names_size != res->ids_size) { +		EBUF_PFI("Sanity check failed: ubi_ids list does not match " +			 "sizeof ubi_names list."); +		rc = -1; +	} + +	/* copy tmp_names to own structure */ +	res->names = (char**) calloc(1, res->names_size * sizeof (char*)); +	if (res->names == NULL) +		goto err; + +	for (i = 0; i < res->names_size; i++) { +		res->names[i] = calloc(PFI_UBI_VOL_NAME_LEN + 1, sizeof(char)); +		if (res->names[i] == NULL) +			goto err; +		strncpy(res->names[i], tmp_names[i], PFI_UBI_VOL_NAME_LEN + 1); +	} + +	goto out; + + err: +	if (res) { +		if (res->names) { +			for (i = 0; i < res->names_size; i++) { +				if (res->names[i]) { +					free(res->names[i]); +				} +			} +			free(res->names); +		} +		if (res->ids) { +			free(res->ids); +		} +		free(res); +		res = NULL; +	} + + out: +	bootenv_list_destroy(&ubi_id_list); +	bootenv_list_destroy(&ubi_name_list); +	if (tmp_names != NULL) +		free(tmp_names); +	*pfi_ubi = res; +	return rc; +} + + +int +free_pdd_data(pdd_data_t* pdd_data) +{ +	if (*pdd_data) { +		free(*pdd_data); +	} +	*pdd_data = NULL; + +	return 0; +} + +int +free_pfi_raw(pfi_raw_t* pfi_raw) +{ +	pfi_raw_t tmp = *pfi_raw; +	if (tmp) { +		if (tmp->starts) +			free(tmp->starts); +		free(tmp); +	} +	*pfi_raw = NULL; + +	return 0; +} + +int +free_pfi_ubi(pfi_ubi_t* pfi_ubi) +{ +	size_t i; +	pfi_ubi_t tmp = *pfi_ubi; +	if (tmp) { +		if (tmp->ids) +			free(tmp->ids); +		if (tmp->names) { +			for (i = 0; i < tmp->names_size; i++) { +				if (tmp->names[i]) { +					free(tmp->names[i]); +				} +			} +			free(tmp->names); +		} +		free(tmp); +	} +	*pfi_ubi = NULL; + +	return 0; +} + + +int +read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi, +		 char* err_buf, size_t err_buf_size) +{ +	int rc = 0; +	char mode[PFI_KEYWORD_LEN]; +	char label[PFI_LABEL_LEN]; + +	*pfi_raws = mk_empty(); pfi_raw_t raw = NULL; +	*pfi_ubis = mk_empty(); pfi_ubi_t ubi = NULL; +	pfi_header pfi_header = NULL; + +	/* read all headers from PFI and store them in lists */ +	rc = pfi_header_init(&pfi_header); +	if (rc != 0) { +		EBUF("Cannot initialize pfi header."); +		goto err; +	} +	while ((rc == 0) && !feof(fp_pfi)) { +		rc = pfi_header_read(fp_pfi, pfi_header); +		if (rc != 0) { +			if (rc == PFI_DATA_START) { +				rc = 0; +				break; /* data section starts, +					  all headers read */ +			} +			else { +				goto err; +			} +		} +		rc = pfi_header_getstring(pfi_header, "label", label, +					  PFI_LABEL_LEN); +		if (rc != 0) { +			EBUF("Cannot read 'label' from PFI."); +			goto err; +		} +		rc = pfi_header_getstring(pfi_header, "mode", mode, +					  PFI_KEYWORD_LEN); +		if (rc != 0) { +			EBUF("Cannot read 'mode' from PFI."); +			goto err; +		} +		if (strcmp(mode, "ubi") == 0) { +			rc = read_pfi_ubi(pfi_header, fp_pfi, &ubi, label, +					  err_buf, err_buf_size); +			if (rc != 0) { +				goto err; +			} +			*pfi_ubis = append_elem(ubi, *pfi_ubis); +		} +		else if (strcmp(mode, "raw") == 0) { +			rc = read_pfi_raw(pfi_header, fp_pfi, &raw, label, +					  err_buf, err_buf_size); +			if (rc != 0) { +				goto err; +			} +			*pfi_raws = append_elem(raw, *pfi_raws); +		} +		else { +			EBUF("Recvieved unknown mode from PFI: %s", mode); +			goto err; +		} +	} +	goto out; + + err: +	*pfi_raws = remove_all((free_func_t)&free_pfi_raw, *pfi_raws); +	*pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, *pfi_ubis); + out: +	pfi_header_destroy(&pfi_header); +	return rc; + +} diff --git a/ubi-utils/sort-me-out/reader.h b/ubi-utils/sort-me-out/reader.h new file mode 100644 index 0000000..715e464 --- /dev/null +++ b/ubi-utils/sort-me-out/reader.h @@ -0,0 +1,87 @@ +#ifndef __READER_H__ +#define __READER_H__ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Oliver Lohmann + * + * Read Platform Description Data (PDD). + */ + +#include <stdint.h> +#include <stdio.h> + +#include "pfi.h" +#include "bootenv.h" +#include "list.h" + +typedef enum flash_type_t { +	NAND_FLASH = 0, +	NOR_FLASH, +} flash_type_t; + +typedef struct pdd_data *pdd_data_t; +typedef struct pfi_raw	*pfi_raw_t; +typedef struct pfi_ubi	*pfi_ubi_t; + +struct pdd_data { +	uint32_t flash_size; +	uint32_t flash_page_size; +	uint32_t eb_size; +	uint32_t vid_hdr_offset; +	flash_type_t flash_type; +}; + +struct pfi_raw { +	uint32_t data_size; +	uint32_t *starts; +	uint32_t starts_size; +	uint32_t crc; +}; + +struct pfi_ubi { +	uint32_t data_size; +	uint32_t alignment; +	uint32_t *ids; +	uint32_t ids_size; +	char	 **names; +	uint32_t names_size; +	uint32_t size; +	enum { pfi_ubi_dynamic, pfi_ubi_static } type; +	int curr_seqnum; /* specifies the seqnum taken in an update, +			    default: 0 (used by pfiflash, ubimirror) */ +	uint32_t crc; +}; + +int read_pdd_data(FILE* fp_pdd, pdd_data_t *pdd_data, +		char *err_buf, size_t err_buf_size); +int read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi, pfi_raw_t *pfi_raw, +		const char *label, char *err_buf, size_t err_buf_size); +int read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi, pfi_ubi_t *pfi_ubi, +		const char *label, char *err_buf, size_t err_buf_size); + +/** + * @brief Reads all pfi headers into list structures, separated by + *	  RAW and UBI sections. + */ +int read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi, +		char* err_buf, size_t err_buf_size); +int free_pdd_data(pdd_data_t *pdd_data); +int free_pfi_raw(pfi_raw_t *raw_pfi); +int free_pfi_ubi(pfi_ubi_t *pfi_ubi); + +#endif /* __READER_H__ */  | 
