UBI: Add basic UBI support to U-Boot (Part 6/8)
This patch adds basic UBI (Unsorted Block Image) support to U-Boot. It's based on the Linux UBI version and basically has a "OS" translation wrapper that defines most Linux specific calls (spin_lock() etc.) into no-ops. Some source code parts have been uncommented by "#ifdef UBI_LINUX". This makes it easier to compare this version with the Linux version and simplifies future UBI ports/bug-fixes from the Linux version. Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Stefan Roese <sr@denx.de>
This commit is contained in:
		
							parent
							
								
									c91a719daa
								
							
						
					
					
						commit
						7e6ee7ad27
					
				|  | @ -25,6 +25,7 @@ char *getenv (char *name); | ||||||
| int setenv (char *varname, char *varvalue); | int setenv (char *varname, char *varvalue); | ||||||
| long simple_strtol(const char *cp,char **endp,unsigned int base); | long simple_strtol(const char *cp,char **endp,unsigned int base); | ||||||
| int strcmp(const char * cs,const char * ct); | int strcmp(const char * cs,const char * ct); | ||||||
|  | int ustrtoul(const char *cp, char **endp, unsigned int base); | ||||||
| #ifdef CONFIG_HAS_UID | #ifdef CONFIG_HAS_UID | ||||||
| void forceenv (char *varname, char *varvalue); | void forceenv (char *varname, char *varvalue); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -73,4 +73,9 @@ struct mtdids { | ||||||
| #define putLabeledWord(x, y)	printf("%s %08x\n", x, (unsigned int)y) | #define putLabeledWord(x, y)	printf("%s %08x\n", x, (unsigned int)y) | ||||||
| #define led_blink(x, y, z, a) | #define led_blink(x, y, z, a) | ||||||
| 
 | 
 | ||||||
|  | /* common/cmd_jffs2.c */ | ||||||
|  | extern int mtdparts_init(void); | ||||||
|  | extern int find_dev_and_part(const char *id, struct mtd_device **dev, | ||||||
|  | 				u8 *part_num, struct part_info **part); | ||||||
|  | 
 | ||||||
| #endif /* load_kernel_h */ | #endif /* load_kernel_h */ | ||||||
|  |  | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | /*
 | ||||||
|  |  * crc32.h | ||||||
|  |  * See linux/lib/crc32.c for license and changes | ||||||
|  |  */ | ||||||
|  | #ifndef _LINUX_CRC32_H | ||||||
|  | #define _LINUX_CRC32_H | ||||||
|  | 
 | ||||||
|  | #include <linux/types.h> | ||||||
|  | //#include <linux/bitrev.h>
 | ||||||
|  | 
 | ||||||
|  | extern u32  crc32_le(u32 crc, unsigned char const *p, size_t len); | ||||||
|  | //extern u32  crc32_be(u32 crc, unsigned char const *p, size_t len);
 | ||||||
|  | 
 | ||||||
|  | #define crc32(seed, data, length)  crc32_le(seed, (unsigned char const *)data, length) | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Helpers for hash table generation of ethernet nics: | ||||||
|  |  * | ||||||
|  |  * Ethernet sends the least significant bit of a byte first, thus crc32_le | ||||||
|  |  * is used. The output of crc32_le is bit reversed [most significant bit | ||||||
|  |  * is in bit nr 0], thus it must be reversed before use. Except for | ||||||
|  |  * nics that bit swap the result internally... | ||||||
|  |  */ | ||||||
|  | //#define ether_crc(length, data)    bitrev32(crc32_le(~0, data, length))
 | ||||||
|  | //#define ether_crc_le(length, data) crc32_le(~0, data, length)
 | ||||||
|  | 
 | ||||||
|  | #endif /* _LINUX_CRC32_H */ | ||||||
|  | @ -0,0 +1,84 @@ | ||||||
|  | /*
 | ||||||
|  |  * MTD partitioning layer definitions | ||||||
|  |  * | ||||||
|  |  * (C) 2000 Nicolas Pitre <nico@cam.org> | ||||||
|  |  * | ||||||
|  |  * This code is GPL | ||||||
|  |  * | ||||||
|  |  * $Id: partitions.h,v 1.17 2005/11/07 11:14:55 gleixner Exp $ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef MTD_PARTITIONS_H | ||||||
|  | #define MTD_PARTITIONS_H | ||||||
|  | 
 | ||||||
|  | #include <linux/types.h> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Partition definition structure: | ||||||
|  |  * | ||||||
|  |  * An array of struct partition is passed along with a MTD object to | ||||||
|  |  * add_mtd_partitions() to create them. | ||||||
|  |  * | ||||||
|  |  * For each partition, these fields are available: | ||||||
|  |  * name: string that will be used to label the partition's MTD device. | ||||||
|  |  * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition | ||||||
|  |  * 	will extend to the end of the master MTD device. | ||||||
|  |  * offset: absolute starting position within the master MTD device; if | ||||||
|  |  * 	defined as MTDPART_OFS_APPEND, the partition will start where the | ||||||
|  |  * 	previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block. | ||||||
|  |  * mask_flags: contains flags that have to be masked (removed) from the | ||||||
|  |  * 	master MTD flag set for the corresponding MTD partition. | ||||||
|  |  * 	For example, to force a read-only partition, simply adding | ||||||
|  |  * 	MTD_WRITEABLE to the mask_flags will do the trick. | ||||||
|  |  * | ||||||
|  |  * Note: writeable partitions require their size and offset be | ||||||
|  |  * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | struct mtd_partition { | ||||||
|  | 	char *name;			/* identifier string */ | ||||||
|  | 	u_int32_t size;			/* partition size */ | ||||||
|  | 	u_int32_t offset;		/* offset within the master MTD space */ | ||||||
|  | 	u_int32_t mask_flags;		/* master MTD flags to mask out for this partition */ | ||||||
|  | 	struct nand_ecclayout *ecclayout;	/* out of band layout for this partition (NAND only)*/ | ||||||
|  | 	struct mtd_info **mtdp;		/* pointer to store the MTD object */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define MTDPART_OFS_NXTBLK	(-2) | ||||||
|  | #define MTDPART_OFS_APPEND	(-1) | ||||||
|  | #define MTDPART_SIZ_FULL	(0) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); | ||||||
|  | int del_mtd_partitions(struct mtd_info *); | ||||||
|  | 
 | ||||||
|  | #if 0 | ||||||
|  | /*
 | ||||||
|  |  * Functions dealing with the various ways of partitioning the space | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | struct mtd_part_parser { | ||||||
|  | 	struct list_head list; | ||||||
|  | 	struct module *owner; | ||||||
|  | 	const char *name; | ||||||
|  | 	int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern int register_mtd_parser(struct mtd_part_parser *parser); | ||||||
|  | extern int deregister_mtd_parser(struct mtd_part_parser *parser); | ||||||
|  | extern int parse_mtd_partitions(struct mtd_info *master, const char **types, | ||||||
|  | 				struct mtd_partition **pparts, unsigned long origin); | ||||||
|  | 
 | ||||||
|  | #define put_partition_parser(p) do { module_put((p)->owner); } while(0) | ||||||
|  | 
 | ||||||
|  | struct device; | ||||||
|  | struct device_node; | ||||||
|  | 
 | ||||||
|  | int __devinit of_mtd_parse_partitions(struct device *dev, | ||||||
|  |                                       struct mtd_info *mtd, | ||||||
|  |                                       struct device_node *node, | ||||||
|  |                                       struct mtd_partition **pparts); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -119,6 +119,30 @@ typedef		__s64		int64_t; | ||||||
|  * Below are truly Linux-specific types that should never collide with |  * Below are truly Linux-specific types that should never collide with | ||||||
|  * any application/library that wants linux/types.h. |  * any application/library that wants linux/types.h. | ||||||
|  */ |  */ | ||||||
|  | #ifdef __CHECKER__ | ||||||
|  | #define __bitwise__ __attribute__((bitwise)) | ||||||
|  | #else | ||||||
|  | #define __bitwise__ | ||||||
|  | #endif | ||||||
|  | #ifdef __CHECK_ENDIAN__ | ||||||
|  | #define __bitwise __bitwise__ | ||||||
|  | #else | ||||||
|  | #define __bitwise | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | typedef __u16 __bitwise __le16; | ||||||
|  | typedef __u16 __bitwise __be16; | ||||||
|  | typedef __u32 __bitwise __le32; | ||||||
|  | typedef __u32 __bitwise __be32; | ||||||
|  | #if defined(__GNUC__) | ||||||
|  | typedef __u64 __bitwise __le64; | ||||||
|  | typedef __u64 __bitwise __be64; | ||||||
|  | #endif | ||||||
|  | typedef __u16 __bitwise __sum16; | ||||||
|  | typedef __u32 __bitwise __wsum; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | typedef unsigned __bitwise__	gfp_t; | ||||||
| 
 | 
 | ||||||
| struct ustat { | struct ustat { | ||||||
| 	__kernel_daddr_t	f_tfree; | 	__kernel_daddr_t	f_tfree; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,217 @@ | ||||||
|  | /*
 | ||||||
|  |  * Header file for UBI support for U-Boot | ||||||
|  |  * | ||||||
|  |  * Adaptation from kernel to U-Boot | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2005-2007 Samsung Electronics | ||||||
|  |  *  Kyungmin Park <kyungmin.park@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef __UBOOT_UBI_H | ||||||
|  | #define __UBOOT_UBI_H | ||||||
|  | 
 | ||||||
|  | #include <common.h> | ||||||
|  | #include <malloc.h> | ||||||
|  | #include <div64.h> | ||||||
|  | #include <linux/crc32.h> | ||||||
|  | #include <linux/mtd/mtd.h> | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_CMD_ONENAND | ||||||
|  | #include <onenand_uboot.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #include <asm/errno.h> | ||||||
|  | 
 | ||||||
|  | #define DPRINTK(format, args...)					\ | ||||||
|  | do {									\ | ||||||
|  | 	printf("%s[%d]: " format "\n", __func__, __LINE__, ##args);	\ | ||||||
|  | } while (0) | ||||||
|  | 
 | ||||||
|  | /* configurable */ | ||||||
|  | #define CONFIG_MTD_UBI_WL_THRESHOLD	4096 | ||||||
|  | #define CONFIG_MTD_UBI_BEB_RESERVE	1 | ||||||
|  | #define UBI_IO_DEBUG			0 | ||||||
|  | 
 | ||||||
|  | /* debug options (Linux: drivers/mtd/ubi/Kconfig.debug) */ | ||||||
|  | #undef CONFIG_MTD_UBI_DEBUG | ||||||
|  | #undef CONFIG_MTD_UBI_DEBUG_PARANOID | ||||||
|  | #undef CONFIG_MTD_UBI_DEBUG_MSG | ||||||
|  | #undef CONFIG_MTD_UBI_DEBUG_MSG_EBA | ||||||
|  | #undef CONFIG_MTD_UBI_DEBUG_MSG_WL | ||||||
|  | #undef CONFIG_MTD_UBI_DEBUG_MSG_IO | ||||||
|  | #undef CONFIG_MTD_UBI_DEBUG_MSG_BLD | ||||||
|  | #define CONFIG_MTD_UBI_DEBUG_DISABLE_BGT | ||||||
|  | 
 | ||||||
|  | /* compiler options */ | ||||||
|  | #define uninitialized_var(x)		x = x | ||||||
|  | 
 | ||||||
|  | /* build.c */ | ||||||
|  | #define get_device(...) | ||||||
|  | #define put_device(...) | ||||||
|  | #define ubi_sysfs_init(...)		0 | ||||||
|  | #define ubi_sysfs_close(...)		do { } while (0) | ||||||
|  | static inline int is_power_of_2(unsigned long n) | ||||||
|  | { | ||||||
|  |         return (n != 0 && ((n & (n - 1)) == 0)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* FIXME */ | ||||||
|  | #define MKDEV(...)			0 | ||||||
|  | #define MAJOR(dev)			0 | ||||||
|  | #define MINOR(dev)			0 | ||||||
|  | 
 | ||||||
|  | #define alloc_chrdev_region(...)	0 | ||||||
|  | #define unregister_chrdev_region(...) | ||||||
|  | 
 | ||||||
|  | #define class_create(...)		__builtin_return_address(0) | ||||||
|  | #define class_create_file(...)		0 | ||||||
|  | #define class_remove_file(...) | ||||||
|  | #define class_destroy(...) | ||||||
|  | #define misc_register(...)		0 | ||||||
|  | #define misc_deregister(...) | ||||||
|  | 
 | ||||||
|  | /* vmt.c */ | ||||||
|  | #define device_register(...)		0 | ||||||
|  | #define volume_sysfs_init(...)		0 | ||||||
|  | #define volume_sysfs_close(...)		do { } while (0) | ||||||
|  | 
 | ||||||
|  | /* kapi.c */ | ||||||
|  | 
 | ||||||
|  | /* eba.c */ | ||||||
|  | 
 | ||||||
|  | /* io.c */ | ||||||
|  | #define init_waitqueue_head(...)	do { } while (0) | ||||||
|  | #define wait_event_interruptible(...)	0 | ||||||
|  | #define wake_up_interruptible(...)	do { } while (0) | ||||||
|  | #define print_hex_dump(...)		do { } while (0) | ||||||
|  | #define dump_stack(...)			do { } while (0) | ||||||
|  | 
 | ||||||
|  | /* wl.c */ | ||||||
|  | #define task_pid_nr(x)			0 | ||||||
|  | #define set_freezable(...)		do { } while (0) | ||||||
|  | #define try_to_freeze(...)		0 | ||||||
|  | #define set_current_state(...)		do { } while (0) | ||||||
|  | #define kthread_should_stop(...)	0 | ||||||
|  | #define schedule()			do { } while (0) | ||||||
|  | 
 | ||||||
|  | /* upd.c */ | ||||||
|  | static inline unsigned long copy_from_user(void *dest, const void *src, | ||||||
|  | 					   unsigned long count) | ||||||
|  | { | ||||||
|  | 	memcpy((void *)dest, (void *)src, count); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* common */ | ||||||
|  | typedef int	spinlock_t; | ||||||
|  | typedef int	wait_queue_head_t; | ||||||
|  | #define spin_lock_init(...) | ||||||
|  | #define spin_lock(...) | ||||||
|  | #define spin_unlock(...) | ||||||
|  | 
 | ||||||
|  | #define mutex_init(...) | ||||||
|  | #define mutex_lock(...) | ||||||
|  | #define mutex_unlock(...) | ||||||
|  | 
 | ||||||
|  | #define init_rwsem(...)			do { } while (0) | ||||||
|  | #define down_read(...)			do { } while (0) | ||||||
|  | #define down_write(...)			do { } while (0) | ||||||
|  | #define down_write_trylock(...)		0 | ||||||
|  | #define up_read(...)			do { } while (0) | ||||||
|  | #define up_write(...)			do { } while (0) | ||||||
|  | 
 | ||||||
|  | struct kmem_cache { int i; }; | ||||||
|  | #define kmem_cache_create(...)		1 | ||||||
|  | #define kmem_cache_alloc(obj, gfp)	malloc(sizeof(struct ubi_wl_entry)) | ||||||
|  | #define kmem_cache_free(obj, size)	free(size) | ||||||
|  | #define kmem_cache_destroy(...) | ||||||
|  | 
 | ||||||
|  | #define cond_resched()			do { } while (0) | ||||||
|  | #define yield()				do { } while (0) | ||||||
|  | 
 | ||||||
|  | #define KERN_WARNING | ||||||
|  | #define KERN_ERR | ||||||
|  | #define KERN_NOTICE | ||||||
|  | #define KERN_DEBUG | ||||||
|  | 
 | ||||||
|  | #define GFP_KERNEL			0 | ||||||
|  | #define GFP_NOFS			1 | ||||||
|  | 
 | ||||||
|  | #define __user | ||||||
|  | #define __init | ||||||
|  | #define __exit | ||||||
|  | 
 | ||||||
|  | #define kthread_create(...)	__builtin_return_address(0) | ||||||
|  | #define kthread_stop(...)	do { } while (0) | ||||||
|  | #define wake_up_process(...)	do { } while (0) | ||||||
|  | 
 | ||||||
|  | #define BUS_ID_SIZE		20 | ||||||
|  | 
 | ||||||
|  | struct rw_semaphore { int i; }; | ||||||
|  | struct device { | ||||||
|  | 	struct device		*parent; | ||||||
|  | 	struct class		*class; | ||||||
|  | 	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */ | ||||||
|  | 	dev_t			devt;	/* dev_t, creates the sysfs "dev" */ | ||||||
|  | 	void	(*release)(struct device *dev); | ||||||
|  | }; | ||||||
|  | struct mutex { int i; }; | ||||||
|  | struct kernel_param { int i; }; | ||||||
|  | 
 | ||||||
|  | struct cdev { | ||||||
|  | 	int owner; | ||||||
|  | 	dev_t dev; | ||||||
|  | }; | ||||||
|  | #define cdev_init(...)		do { } while (0) | ||||||
|  | #define cdev_add(...)		0 | ||||||
|  | #define cdev_del(...)		do { } while (0) | ||||||
|  | 
 | ||||||
|  | #define MAX_ERRNO		4095 | ||||||
|  | #define IS_ERR_VALUE(x)		((x) >= (unsigned long)-MAX_ERRNO) | ||||||
|  | 
 | ||||||
|  | static inline void *ERR_PTR(long error) | ||||||
|  | { | ||||||
|  | 	return (void *) error; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline long PTR_ERR(const void *ptr) | ||||||
|  | { | ||||||
|  | 	return (long) ptr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline long IS_ERR(const void *ptr) | ||||||
|  | { | ||||||
|  | 	return IS_ERR_VALUE((unsigned long)ptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Force a compilation error if condition is true */ | ||||||
|  | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) | ||||||
|  | 
 | ||||||
|  | /* module */ | ||||||
|  | #define THIS_MODULE		0 | ||||||
|  | #define try_module_get(...)	0 | ||||||
|  | #define module_put(...)		do { } while (0) | ||||||
|  | #define module_init(...) | ||||||
|  | #define module_exit(...) | ||||||
|  | #define EXPORT_SYMBOL(...) | ||||||
|  | #define EXPORT_SYMBOL_GPL(...) | ||||||
|  | #define module_param_call(...) | ||||||
|  | #define MODULE_PARM_DESC(...) | ||||||
|  | #define MODULE_VERSION(...) | ||||||
|  | #define MODULE_DESCRIPTION(...) | ||||||
|  | #define MODULE_AUTHOR(...) | ||||||
|  | #define MODULE_LICENSE(...) | ||||||
|  | 
 | ||||||
|  | #include "../drivers/mtd/ubi/ubi.h" | ||||||
|  | 
 | ||||||
|  | /* functions */ | ||||||
|  | extern int ubi_mtd_param_parse(const char *val, struct kernel_param *kp); | ||||||
|  | extern int ubi_init(void); | ||||||
|  | 
 | ||||||
|  | extern struct ubi_device *ubi_devices[]; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -55,6 +55,29 @@ long simple_strtol(const char *cp,char **endp,unsigned int base) | ||||||
| 	return simple_strtoul(cp,endp,base); | 	return simple_strtoul(cp,endp,base); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int ustrtoul(const char *cp, char **endp, unsigned int base) | ||||||
|  | { | ||||||
|  | 	unsigned long result = simple_strtoul(cp, endp, base); | ||||||
|  | 	switch (**endp) { | ||||||
|  | 	case 'G' : | ||||||
|  | 		result *= 1024; | ||||||
|  | 		/* fall through */ | ||||||
|  | 	case 'M': | ||||||
|  | 		result *= 1024; | ||||||
|  | 		/* fall through */ | ||||||
|  | 	case 'K': | ||||||
|  | 	case 'k': | ||||||
|  | 		result *= 1024; | ||||||
|  | 		if ((*endp)[1] == 'i') { | ||||||
|  | 			if ((*endp)[2] == 'B') | ||||||
|  | 				(*endp) += 3; | ||||||
|  | 			else | ||||||
|  | 				(*endp) += 2; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #ifdef CONFIG_SYS_64BIT_STRTOUL | #ifdef CONFIG_SYS_64BIT_STRTOUL | ||||||
| unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base) | unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base) | ||||||
| { | { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue