UBI: Add basic UBI support to U-Boot (Part 6/8)
authorKyungmin Park <kyungmin.park@samsung.com>
Wed, 19 Nov 2008 15:32:36 +0000 (16:32 +0100)
committerStefan Roese <sr@denx.de>
Wed, 19 Nov 2008 19:34:39 +0000 (20:34 +0100)
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>
include/exports.h
include/jffs2/load_kernel.h
include/linux/crc32.h [new file with mode: 0644]
include/linux/mtd/partitions.h [new file with mode: 0644]
include/linux/types.h
include/ubi_uboot.h [new file with mode: 0644]
lib_generic/vsprintf.c

index 6377875bc9a9a151f8b182a32c32c0b1458fd7a7..0620e9eb896e65e588263fe933c99827d78f432e 100644 (file)
@@ -25,6 +25,7 @@ char *getenv (char *name);
 int setenv (char *varname, char *varvalue);
 long simple_strtol(const char *cp,char **endp,unsigned int base);
 int strcmp(const char * cs,const char * ct);
+int ustrtoul(const char *cp, char **endp, unsigned int base);
 #ifdef CONFIG_HAS_UID
 void forceenv (char *varname, char *varvalue);
 #endif
index 551fd0c442ace592053e3f1b8dd787d3bed4a94e..e9b7d6e7c9d454cfe6a8af01c2b8d74453d40838 100644 (file)
@@ -73,4 +73,9 @@ struct mtdids {
 #define putLabeledWord(x, y)   printf("%s %08x\n", x, (unsigned int)y)
 #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 */
diff --git a/include/linux/crc32.h b/include/linux/crc32.h
new file mode 100644 (file)
index 0000000..e133157
--- /dev/null
@@ -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 */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
new file mode 100644 (file)
index 0000000..b41e5f5
--- /dev/null
@@ -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
index df4808fcdf45578b502ba25e7b287689461acb92..1b0b4a44c456a6d20303cf6de31293a7840911f6 100644 (file)
@@ -119,6 +119,30 @@ typedef            __s64           int64_t;
  * Below are truly Linux-specific types that should never collide with
  * 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 {
        __kernel_daddr_t        f_tfree;
diff --git a/include/ubi_uboot.h b/include/ubi_uboot.h
new file mode 100644 (file)
index 0000000..295f2c0
--- /dev/null
@@ -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
index 6e903dbb3d5ef8066c266ec41393fce1eca96a15..767dde1ba7c272d03f678d87e46ab2024e6c707d 100644 (file)
@@ -55,6 +55,29 @@ long simple_strtol(const char *cp,char **endp,unsigned int 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
 unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base)
 {