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>master
parent
7e6ee7ad27
commit
47ae6693f5
@ -0,0 +1,186 @@ |
||||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
* |
||||
* Author: Artem Bityutskiy (Битюцкий Артём) |
||||
*/ |
||||
|
||||
#ifndef __LINUX_UBI_H__ |
||||
#define __LINUX_UBI_H__ |
||||
|
||||
//#include <asm/ioctl.h>
|
||||
#include <linux/types.h> |
||||
#include <mtd/ubi-user.h> |
||||
|
||||
/*
|
||||
* enum ubi_open_mode - UBI volume open mode constants. |
||||
* |
||||
* UBI_READONLY: read-only mode |
||||
* UBI_READWRITE: read-write mode |
||||
* UBI_EXCLUSIVE: exclusive mode |
||||
*/ |
||||
enum { |
||||
UBI_READONLY = 1, |
||||
UBI_READWRITE, |
||||
UBI_EXCLUSIVE |
||||
}; |
||||
|
||||
/**
|
||||
* struct ubi_volume_info - UBI volume description data structure. |
||||
* @vol_id: volume ID |
||||
* @ubi_num: UBI device number this volume belongs to |
||||
* @size: how many physical eraseblocks are reserved for this volume |
||||
* @used_bytes: how many bytes of data this volume contains |
||||
* @used_ebs: how many physical eraseblocks of this volume actually contain any |
||||
* data |
||||
* @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) |
||||
* @corrupted: non-zero if the volume is corrupted (static volumes only) |
||||
* @upd_marker: non-zero if the volume has update marker set |
||||
* @alignment: volume alignment |
||||
* @usable_leb_size: how many bytes are available in logical eraseblocks of |
||||
* this volume |
||||
* @name_len: volume name length |
||||
* @name: volume name |
||||
* @cdev: UBI volume character device major and minor numbers |
||||
* |
||||
* The @corrupted flag is only relevant to static volumes and is always zero |
||||
* for dynamic ones. This is because UBI does not care about dynamic volume |
||||
* data protection and only cares about protecting static volume data. |
||||
* |
||||
* The @upd_marker flag is set if the volume update operation was interrupted. |
||||
* Before touching the volume data during the update operation, UBI first sets |
||||
* the update marker flag for this volume. If the volume update operation was |
||||
* further interrupted, the update marker indicates this. If the update marker |
||||
* is set, the contents of the volume is certainly damaged and a new volume |
||||
* update operation has to be started. |
||||
* |
||||
* To put it differently, @corrupted and @upd_marker fields have different |
||||
* semantics: |
||||
* o the @corrupted flag means that this static volume is corrupted for some |
||||
* reasons, but not because an interrupted volume update |
||||
* o the @upd_marker field means that the volume is damaged because of an |
||||
* interrupted update operation. |
||||
* |
||||
* I.e., the @corrupted flag is never set if the @upd_marker flag is set. |
||||
* |
||||
* The @used_bytes and @used_ebs fields are only really needed for static |
||||
* volumes and contain the number of bytes stored in this static volume and how |
||||
* many eraseblock this data occupies. In case of dynamic volumes, the |
||||
* @used_bytes field is equivalent to @size*@usable_leb_size, and the @used_ebs |
||||
* field is equivalent to @size. |
||||
* |
||||
* In general, logical eraseblock size is a property of the UBI device, not |
||||
* of the UBI volume. Indeed, the logical eraseblock size depends on the |
||||
* physical eraseblock size and on how much bytes UBI headers consume. But |
||||
* because of the volume alignment (@alignment), the usable size of logical |
||||
* eraseblocks if a volume may be less. The following equation is true: |
||||
* @usable_leb_size = LEB size - (LEB size mod @alignment), |
||||
* where LEB size is the logical eraseblock size defined by the UBI device. |
||||
* |
||||
* The alignment is multiple to the minimal flash input/output unit size or %1 |
||||
* if all the available space is used. |
||||
* |
||||
* To put this differently, alignment may be considered is a way to change |
||||
* volume logical eraseblock sizes. |
||||
*/ |
||||
struct ubi_volume_info { |
||||
int ubi_num; |
||||
int vol_id; |
||||
int size; |
||||
long long used_bytes; |
||||
int used_ebs; |
||||
int vol_type; |
||||
int corrupted; |
||||
int upd_marker; |
||||
int alignment; |
||||
int usable_leb_size; |
||||
int name_len; |
||||
const char *name; |
||||
dev_t cdev; |
||||
}; |
||||
|
||||
/**
|
||||
* struct ubi_device_info - UBI device description data structure. |
||||
* @ubi_num: ubi device number |
||||
* @leb_size: logical eraseblock size on this UBI device |
||||
* @min_io_size: minimal I/O unit size |
||||
* @ro_mode: if this device is in read-only mode |
||||
* @cdev: UBI character device major and minor numbers |
||||
* |
||||
* Note, @leb_size is the logical eraseblock size offered by the UBI device. |
||||
* Volumes of this UBI device may have smaller logical eraseblock size if their |
||||
* alignment is not equivalent to %1. |
||||
*/ |
||||
struct ubi_device_info { |
||||
int ubi_num; |
||||
int leb_size; |
||||
int min_io_size; |
||||
int ro_mode; |
||||
dev_t cdev; |
||||
}; |
||||
|
||||
/* UBI descriptor given to users when they open UBI volumes */ |
||||
struct ubi_volume_desc; |
||||
|
||||
int ubi_get_device_info(int ubi_num, struct ubi_device_info *di); |
||||
void ubi_get_volume_info(struct ubi_volume_desc *desc, |
||||
struct ubi_volume_info *vi); |
||||
struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode); |
||||
struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, |
||||
int mode); |
||||
void ubi_close_volume(struct ubi_volume_desc *desc); |
||||
int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, |
||||
int len, int check); |
||||
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, |
||||
int offset, int len, int dtype); |
||||
int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, |
||||
int len, int dtype); |
||||
int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum); |
||||
int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum); |
||||
int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype); |
||||
int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum); |
||||
|
||||
/*
|
||||
* This function is the same as the 'ubi_leb_read()' function, but it does not |
||||
* provide the checking capability. |
||||
*/ |
||||
static inline int ubi_read(struct ubi_volume_desc *desc, int lnum, char *buf, |
||||
int offset, int len) |
||||
{ |
||||
return ubi_leb_read(desc, lnum, buf, offset, len, 0); |
||||
} |
||||
|
||||
/*
|
||||
* This function is the same as the 'ubi_leb_write()' functions, but it does |
||||
* not have the data type argument. |
||||
*/ |
||||
static inline int ubi_write(struct ubi_volume_desc *desc, int lnum, |
||||
const void *buf, int offset, int len) |
||||
{ |
||||
return ubi_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN); |
||||
} |
||||
|
||||
/*
|
||||
* This function is the same as the 'ubi_leb_change()' functions, but it does |
||||
* not have the data type argument. |
||||
*/ |
||||
static inline int ubi_change(struct ubi_volume_desc *desc, int lnum, |
||||
const void *buf, int len) |
||||
{ |
||||
return ubi_leb_change(desc, lnum, buf, len, UBI_UNKNOWN); |
||||
} |
||||
|
||||
#endif /* !__LINUX_UBI_H__ */ |
@ -0,0 +1,268 @@ |
||||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
* |
||||
* Author: Artem Bityutskiy (Битюцкий Артём) |
||||
*/ |
||||
|
||||
#ifndef __UBI_USER_H__ |
||||
#define __UBI_USER_H__ |
||||
|
||||
/*
|
||||
* UBI device creation (the same as MTD device attachment) |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* MTD devices may be attached using %UBI_IOCATT ioctl command of the UBI |
||||
* control device. The caller has to properly fill and pass |
||||
* &struct ubi_attach_req object - UBI will attach the MTD device specified in |
||||
* the request and return the newly created UBI device number as the ioctl |
||||
* return value. |
||||
* |
||||
* UBI device deletion (the same as MTD device detachment) |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* An UBI device maybe deleted with %UBI_IOCDET ioctl command of the UBI |
||||
* control device. |
||||
* |
||||
* UBI volume creation |
||||
* ~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* UBI volumes are created via the %UBI_IOCMKVOL IOCTL command of UBI character |
||||
* device. A &struct ubi_mkvol_req object has to be properly filled and a |
||||
* pointer to it has to be passed to the IOCTL. |
||||
* |
||||
* UBI volume deletion |
||||
* ~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* To delete a volume, the %UBI_IOCRMVOL IOCTL command of the UBI character |
||||
* device should be used. A pointer to the 32-bit volume ID hast to be passed |
||||
* to the IOCTL. |
||||
* |
||||
* UBI volume re-size |
||||
* ~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* To re-size a volume, the %UBI_IOCRSVOL IOCTL command of the UBI character |
||||
* device should be used. A &struct ubi_rsvol_req object has to be properly |
||||
* filled and a pointer to it has to be passed to the IOCTL. |
||||
* |
||||
* UBI volume update |
||||
* ~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Volume update should be done via the %UBI_IOCVOLUP IOCTL command of the |
||||
* corresponding UBI volume character device. A pointer to a 64-bit update |
||||
* size should be passed to the IOCTL. After this, UBI expects user to write |
||||
* this number of bytes to the volume character device. The update is finished |
||||
* when the claimed number of bytes is passed. So, the volume update sequence |
||||
* is something like: |
||||
* |
||||
* fd = open("/dev/my_volume"); |
||||
* ioctl(fd, UBI_IOCVOLUP, &image_size); |
||||
* write(fd, buf, image_size); |
||||
* close(fd); |
||||
* |
||||
* Atomic eraseblock change |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Atomic eraseblock change operation is done via the %UBI_IOCEBCH IOCTL |
||||
* command of the corresponding UBI volume character device. A pointer to |
||||
* &struct ubi_leb_change_req has to be passed to the IOCTL. Then the user is |
||||
* expected to write the requested amount of bytes. This is similar to the |
||||
* "volume update" IOCTL. |
||||
*/ |
||||
|
||||
/*
|
||||
* When a new UBI volume or UBI device is created, users may either specify the |
||||
* volume/device number they want to create or to let UBI automatically assign |
||||
* the number using these constants. |
||||
*/ |
||||
#define UBI_VOL_NUM_AUTO (-1) |
||||
#define UBI_DEV_NUM_AUTO (-1) |
||||
|
||||
/* Maximum volume name length */ |
||||
#define UBI_MAX_VOLUME_NAME 127 |
||||
|
||||
/* IOCTL commands of UBI character devices */ |
||||
|
||||
#define UBI_IOC_MAGIC 'o' |
||||
|
||||
/* Create an UBI volume */ |
||||
#define UBI_IOCMKVOL _IOW(UBI_IOC_MAGIC, 0, struct ubi_mkvol_req) |
||||
/* Remove an UBI volume */ |
||||
#define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t) |
||||
/* Re-size an UBI volume */ |
||||
#define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req) |
||||
|
||||
/* IOCTL commands of the UBI control character device */ |
||||
|
||||
#define UBI_CTRL_IOC_MAGIC 'o' |
||||
|
||||
/* Attach an MTD device */ |
||||
#define UBI_IOCATT _IOW(UBI_CTRL_IOC_MAGIC, 64, struct ubi_attach_req) |
||||
/* Detach an MTD device */ |
||||
#define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, int32_t) |
||||
|
||||
/* IOCTL commands of UBI volume character devices */ |
||||
|
||||
#define UBI_VOL_IOC_MAGIC 'O' |
||||
|
||||
/* Start UBI volume update */ |
||||
#define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t) |
||||
/* An eraseblock erasure command, used for debugging, disabled by default */ |
||||
#define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t) |
||||
/* An atomic eraseblock change command */ |
||||
#define UBI_IOCEBCH _IOW(UBI_VOL_IOC_MAGIC, 2, int32_t) |
||||
|
||||
/* Maximum MTD device name length supported by UBI */ |
||||
#define MAX_UBI_MTD_NAME_LEN 127 |
||||
|
||||
/*
|
||||
* UBI data type hint constants. |
||||
* |
||||
* UBI_LONGTERM: long-term data |
||||
* UBI_SHORTTERM: short-term data |
||||
* UBI_UNKNOWN: data persistence is unknown |
||||
* |
||||
* These constants are used when data is written to UBI volumes in order to |
||||
* help the UBI wear-leveling unit to find more appropriate physical |
||||
* eraseblocks. |
||||
*/ |
||||
enum { |
||||
UBI_LONGTERM = 1, |
||||
UBI_SHORTTERM = 2, |
||||
UBI_UNKNOWN = 3, |
||||
}; |
||||
|
||||
/*
|
||||
* UBI volume type constants. |
||||
* |
||||
* @UBI_DYNAMIC_VOLUME: dynamic volume |
||||
* @UBI_STATIC_VOLUME: static volume |
||||
*/ |
||||
enum { |
||||
UBI_DYNAMIC_VOLUME = 3, |
||||
UBI_STATIC_VOLUME = 4, |
||||
}; |
||||
|
||||
/**
|
||||
* struct ubi_attach_req - attach MTD device request. |
||||
* @ubi_num: UBI device number to create |
||||
* @mtd_num: MTD device number to attach |
||||
* @vid_hdr_offset: VID header offset (use defaults if %0) |
||||
* @padding: reserved for future, not used, has to be zeroed |
||||
* |
||||
* This data structure is used to specify MTD device UBI has to attach and the |
||||
* parameters it has to use. The number which should be assigned to the new UBI |
||||
* device is passed in @ubi_num. UBI may automatically assign the number if |
||||
* @UBI_DEV_NUM_AUTO is passed. In this case, the device number is returned in |
||||
* @ubi_num. |
||||
* |
||||
* Most applications should pass %0 in @vid_hdr_offset to make UBI use default |
||||
* offset of the VID header within physical eraseblocks. The default offset is |
||||
* the next min. I/O unit after the EC header. For example, it will be offset |
||||
* 512 in case of a 512 bytes page NAND flash with no sub-page support. Or |
||||
* it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages. |
||||
* |
||||
* But in rare cases, if this optimizes things, the VID header may be placed to |
||||
* a different offset. For example, the boot-loader might do things faster if the |
||||
* VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. As |
||||
* the boot-loader would not normally need to read EC headers (unless it needs |
||||
* UBI in RW mode), it might be faster to calculate ECC. This is weird example, |
||||
* but it real-life example. So, in this example, @vid_hdr_offer would be |
||||
* 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes |
||||
* aligned, which is OK, as UBI is clever enough to realize this is 4th sub-page |
||||
* of the first page and add needed padding. |
||||
*/ |
||||
struct ubi_attach_req { |
||||
int32_t ubi_num; |
||||
int32_t mtd_num; |
||||
int32_t vid_hdr_offset; |
||||
uint8_t padding[12]; |
||||
}; |
||||
|
||||
/**
|
||||
* struct ubi_mkvol_req - volume description data structure used in |
||||
* volume creation requests. |
||||
* @vol_id: volume number |
||||
* @alignment: volume alignment |
||||
* @bytes: volume size in bytes |
||||
* @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) |
||||
* @padding1: reserved for future, not used, has to be zeroed |
||||
* @name_len: volume name length |
||||
* @padding2: reserved for future, not used, has to be zeroed |
||||
* @name: volume name |
||||
* |
||||
* This structure is used by user-space programs when creating new volumes. The |
||||
* @used_bytes field is only necessary when creating static volumes. |
||||
* |
||||
* The @alignment field specifies the required alignment of the volume logical |
||||
* eraseblock. This means, that the size of logical eraseblocks will be aligned |
||||
* to this number, i.e., |
||||
* (UBI device logical eraseblock size) mod (@alignment) = 0. |
||||
* |
||||
* To put it differently, the logical eraseblock of this volume may be slightly |
||||
* shortened in order to make it properly aligned. The alignment has to be |
||||
* multiple of the flash minimal input/output unit, or %1 to utilize the entire |
||||
* available space of logical eraseblocks. |
||||
* |
||||
* The @alignment field may be useful, for example, when one wants to maintain |
||||
* a block device on top of an UBI volume. In this case, it is desirable to fit |
||||
* an integer number of blocks in logical eraseblocks of this UBI volume. With |
||||
* alignment it is possible to update this volume using plane UBI volume image |
||||
* BLOBs, without caring about how to properly align them. |
||||
*/ |
||||
struct ubi_mkvol_req { |
||||
int32_t vol_id; |
||||
int32_t alignment; |
||||
int64_t bytes; |
||||
int8_t vol_type; |
||||
int8_t padding1; |
||||
int16_t name_len; |
||||
int8_t padding2[4]; |
||||
char name[UBI_MAX_VOLUME_NAME + 1]; |
||||
} __attribute__ ((packed)); |
||||
|
||||
/**
|
||||
* struct ubi_rsvol_req - a data structure used in volume re-size requests. |
||||
* @vol_id: ID of the volume to re-size |
||||
* @bytes: new size of the volume in bytes |
||||
* |
||||
* Re-sizing is possible for both dynamic and static volumes. But while dynamic |
||||
* volumes may be re-sized arbitrarily, static volumes cannot be made to be |
||||
* smaller then the number of bytes they bear. To arbitrarily shrink a static |
||||
* volume, it must be wiped out first (by means of volume update operation with |
||||
* zero number of bytes). |
||||
*/ |
||||
struct ubi_rsvol_req { |
||||
int64_t bytes; |
||||
int32_t vol_id; |
||||
} __attribute__ ((packed)); |
||||
|
||||
/**
|
||||
* struct ubi_leb_change_req - a data structure used in atomic logical |
||||
* eraseblock change requests. |
||||
* @lnum: logical eraseblock number to change |
||||
* @bytes: how many bytes will be written to the logical eraseblock |
||||
* @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN) |
||||
* @padding: reserved for future, not used, has to be zeroed |
||||
*/ |
||||
struct ubi_leb_change_req { |
||||
int32_t lnum; |
||||
int32_t bytes; |
||||
uint8_t dtype; |
||||
uint8_t padding[7]; |
||||
} __attribute__ ((packed)); |
||||
|
||||
#endif /* __UBI_USER_H__ */ |
Loading…
Reference in new issue