mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-04-21 12:27:27 +03:00
move platform specific base-files into target/linux/<targetname>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@5621 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
12
target/linux/brcm-2.4/base-files.mk
Normal file
12
target/linux/brcm-2.4/base-files.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
define Build/Compile
|
||||
$(call Build/Compile/Default)
|
||||
$(TARGET_CC) -I $(PLATFORM_DIR)/src -o $(PKG_BUILD_DIR)/jffs2root $(PLATFORM_DIR)/src/jffs2root.c
|
||||
endef
|
||||
|
||||
define Package/base-files/install-target
|
||||
rm -f $(1)/etc/config/network
|
||||
mkdir -p $(1)/sbin
|
||||
$(CP) $(PKG_BUILD_DIR)/jffs2root $(1)/sbin
|
||||
endef
|
||||
|
||||
|
||||
128
target/linux/brcm-2.4/base-files/bin/firstboot
Executable file
128
target/linux/brcm-2.4/base-files/bin/firstboot
Executable file
@@ -0,0 +1,128 @@
|
||||
#!/bin/sh
|
||||
# $Id$
|
||||
. /etc/functions.sh
|
||||
|
||||
partname="OpenWrt"
|
||||
mtdpart="$(find_mtd_part $partname)"
|
||||
|
||||
rom=$(awk '/squashfs/ {print $2}' /proc/mounts)
|
||||
jffs=$(awk '/jffs2/ {print $2}' /proc/mounts)
|
||||
|
||||
dupe() { # <new_root> <old_root>
|
||||
cd $1
|
||||
echo -n "creating directories... "
|
||||
{
|
||||
cd $2
|
||||
find . -xdev -type d
|
||||
echo "./dev ./jffs ./mnt ./proc ./tmp"
|
||||
# xdev skips mounted directories
|
||||
cd $1
|
||||
} | xargs mkdir -p
|
||||
echo "done"
|
||||
|
||||
echo -n "setting up symlinks... "
|
||||
for file in $(cd $2; find . -xdev -type f;); do
|
||||
case "$file" in
|
||||
./rom/note) ;; #nothing
|
||||
./etc/config*|\
|
||||
./usr/lib/ipkg/info/*) cp -af $2/$file $file;;
|
||||
*) ln -sf /rom/${file#./*} $file;;
|
||||
esac
|
||||
done
|
||||
for file in $(cd $2; find . -xdev -type l;); do
|
||||
cp -af $2/${file#./*} $file
|
||||
done
|
||||
echo "done"
|
||||
}
|
||||
|
||||
pivot() { # <new_root> <old_root>
|
||||
mount -o move /proc $1/proc && \
|
||||
pivot_root $1 $1$2 && {
|
||||
mount -o move $2/dev /dev
|
||||
mount -o move $2/tmp /tmp
|
||||
mount -o move $2/jffs /jffs 2>&-
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
fopivot() { # <rw_root> <ro_root> <dupe?>
|
||||
root=$1
|
||||
{
|
||||
mount -t mini_fo -o base=/,sto=$1 $1 /mnt 2>&- && root=/mnt
|
||||
} || {
|
||||
[ "$3" = "1" ] && {
|
||||
mount | grep "on $1 type" 2>&- 1>&- || mount -o bind $1 $1
|
||||
dupe $1 $rom
|
||||
}
|
||||
}
|
||||
pivot $root $2
|
||||
}
|
||||
|
||||
ramoverlay() {
|
||||
mkdir -p /tmp/root
|
||||
fopivot /tmp/root /rom 1
|
||||
}
|
||||
|
||||
# invoked as an executable
|
||||
[ "${0##*/}" = "firstboot" ] && {
|
||||
|
||||
[ -z "$mtdpart" ] && {
|
||||
echo "MTD partition not found."
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -z "$rom" ] && {
|
||||
echo "You do not have a squashfs partition; aborting"
|
||||
echo "(firstboot cannot be run on jffs2 based firmwares)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ "$1" = "switch2jffs" ] && {
|
||||
mtd erase "$partname"
|
||||
|
||||
# try to avoid fs changing while copying
|
||||
mount -o remount,ro none / 2>&-
|
||||
|
||||
# copy ramoverlay to jffs2
|
||||
mount "$mtdpart" /rom/jffs -t jffs2
|
||||
echo -n "copying files ... "
|
||||
cp -a /tmp/root/* /rom/jffs 2>&-
|
||||
echo "done"
|
||||
|
||||
# switch back to squashfs (temporarily)
|
||||
# and park the ramdisk ontop of /tmp/root
|
||||
pivot /rom /mnt
|
||||
mount -o move /mnt /tmp/root
|
||||
|
||||
# /jffs is the overlay
|
||||
# /rom is the readonly
|
||||
fopivot /jffs /rom
|
||||
|
||||
# try to get rid of /tmp/root
|
||||
# this will almost always fail
|
||||
umount /tmp/root 2>&-
|
||||
|
||||
# fs is clean
|
||||
jffs2root --clean
|
||||
exit 0
|
||||
}
|
||||
|
||||
# script run manually
|
||||
[ \! -z "$jffs" ] && {
|
||||
echo "firstboot has already been run"
|
||||
echo "jffs2 partition is mounted, only resetting files"
|
||||
grep mini_fo /proc/filesystems >&-
|
||||
[ $? != 0 ] && {
|
||||
dupe $jffs $rom
|
||||
exit 0
|
||||
} || {
|
||||
rm -rf $jffs/* 2>&-
|
||||
mount -o remount $jffs / 2>&-
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
|
||||
mtd erase "$partname"
|
||||
mount "$mtdpart" /jffs -t jffs2
|
||||
fopivot /jffs /rom 1
|
||||
}
|
||||
28
target/linux/brcm-2.4/base-files/etc/diag.sh
Normal file
28
target/linux/brcm-2.4/base-files/etc/diag.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
set_led() {
|
||||
local led="$1"
|
||||
local state="$2"
|
||||
[ -f "/proc/diag/led/$1" ] && echo "$state" > "/proc/diag/led/$1"
|
||||
}
|
||||
|
||||
set_state() {
|
||||
case "$1" in
|
||||
preinit)
|
||||
set_led dmz 1
|
||||
set_led diag 1
|
||||
set_led power 0
|
||||
;;
|
||||
failsafe)
|
||||
set_led diag f
|
||||
set_led power f
|
||||
set_led dmz f
|
||||
;;
|
||||
done)
|
||||
set_led dmz 0
|
||||
set_led diag 0
|
||||
set_led power 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
15
target/linux/brcm-2.4/base-files/etc/init.d/done
Executable file
15
target/linux/brcm-2.4/base-files/etc/init.d/done
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
START=95
|
||||
boot() {
|
||||
[ -d /tmp/root ] && {
|
||||
lock /tmp/.switch2jffs
|
||||
firstboot switch2jffs
|
||||
lock -u /tmp/.switch2jffs
|
||||
}
|
||||
|
||||
# set leds to normal state
|
||||
. /etc/diag.sh
|
||||
set_state done
|
||||
}
|
||||
98
target/linux/brcm-2.4/base-files/etc/init.d/netconfig
Executable file
98
target/linux/brcm-2.4/base-files/etc/init.d/netconfig
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
START=05
|
||||
|
||||
start() {
|
||||
[ -e /etc/config/network ] && exit 0
|
||||
|
||||
mkdir -p /etc/config
|
||||
|
||||
(
|
||||
if grep -E 'mtd0: 000(6|a)0000' /proc/mtd 2>&- >&-; then
|
||||
# WGT634u
|
||||
echo boardtype=wgt634u
|
||||
else
|
||||
strings /dev/mtdblock/3
|
||||
fi
|
||||
) | awk '
|
||||
function p(cfgname, name) {
|
||||
if (c[name] != "") print " option " cfgname " \"" c[name] "\""
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
FS="="
|
||||
c["lan_ifname"]="eth0.0"
|
||||
c["wan_ifname"]="eth0.1"
|
||||
c["vlan0ports"]="1 2 3 4 5*"
|
||||
c["vlan1ports"]="0 5"
|
||||
}
|
||||
|
||||
($1 == "boardnum") || ($1 == "boardtype") || ($1 == "boardflags") {
|
||||
nvram[$1] = $2
|
||||
}
|
||||
|
||||
END {
|
||||
# v1 hardware
|
||||
if (nvram["boardtype"] == "bcm94710dev") {
|
||||
# Asus WL-500g
|
||||
if (nvram["boardnum"] == "asusX") {
|
||||
c["lan_ifname"]="eth0 eth1" # FIXME
|
||||
c["wan_ifname"]=""
|
||||
}
|
||||
}
|
||||
if (nvram["boardtype"] == "bcm94710r4") {
|
||||
# Toshiba WRC-1000
|
||||
c["lan_ifname"] = "eth0"
|
||||
c["wan_ifname"] = "eth1"
|
||||
}
|
||||
if (nvram["boardtype"] == "wgt634u") {
|
||||
c["vlan0ports"] = "0 1 2 3 5*"
|
||||
c["vlan1ports"] = "4 5"
|
||||
}
|
||||
if ((nvram["boardtype"] == "0x0467") || (nvram["boardtype"] == "0x042f")) {
|
||||
if (nvram["boardnum"] == "45") {
|
||||
c["vlan0ports"] = "1 2 3 4 5*"
|
||||
c["vlan1ports"] = "0 5"
|
||||
} else {
|
||||
c["vlan0ports"] = "0 1 2 3 5*"
|
||||
c["vlan1ports"] = "4 5"
|
||||
}
|
||||
}
|
||||
|
||||
# WAP54G
|
||||
if ((nvram["boardnum"] == "2") || \
|
||||
(nvram["boardnum"] == "1024")) {
|
||||
c["lan_ifname"]="eth0"
|
||||
c["wan_ifname"]=""
|
||||
}
|
||||
|
||||
print "#### VLAN configuration "
|
||||
print "config switch eth0"
|
||||
p("vlan0", "vlan0ports")
|
||||
p("vlan1", "vlan1ports")
|
||||
print ""
|
||||
print ""
|
||||
print "#### Loopback configuration"
|
||||
print "config interface loopback"
|
||||
print " option ifname \"lo\""
|
||||
print " option proto static"
|
||||
print " option ipaddr 127.0.0.1"
|
||||
print " option netmask 255.0.0.0"
|
||||
print ""
|
||||
print ""
|
||||
print "#### LAN configuration"
|
||||
print "config interface lan"
|
||||
print " option type bridge"
|
||||
p("ifname", "lan_ifname")
|
||||
print " option proto static"
|
||||
print " option ipaddr 192.168.1.1"
|
||||
print " option netmask 255.255.255.0"
|
||||
print ""
|
||||
print ""
|
||||
print "#### WAN configuration"
|
||||
print "config interface wan"
|
||||
p("ifname", "wan_ifname")
|
||||
print " option proto dhcp"
|
||||
}' > /etc/config/network
|
||||
}
|
||||
74
target/linux/brcm-2.4/base-files/etc/preinit
Executable file
74
target/linux/brcm-2.4/base-files/etc/preinit
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
. /etc/functions.sh
|
||||
. /etc/diag.sh
|
||||
|
||||
failsafe() {
|
||||
lock /tmp/.failsafe
|
||||
|
||||
echo "0 1 2 3 4 5u*" > /proc/switch/eth0/vlan/0/ports
|
||||
|
||||
set_state failsafe
|
||||
[ -x "/usr/sbin/nvram" ] && {
|
||||
[ "$(nvram get boot_wait)" != "on" ] && {
|
||||
nvram set boot_wait=on
|
||||
nvram commit
|
||||
}
|
||||
}
|
||||
|
||||
netmsg 192.168.1.255 "Entering Failsafe!"
|
||||
telnetd -l /bin/login <> /dev/null 2>&1
|
||||
|
||||
ash --login
|
||||
lock -u /tmp/.failsafe
|
||||
}
|
||||
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
|
||||
mount none /proc -t proc
|
||||
size=$(awk '/Mem:/ {l=5242880;print((s=$2/2)<l)?$2-l:s}' /proc/meminfo)
|
||||
mount none /tmp -t tmpfs -o size=$size
|
||||
|
||||
insmod diag
|
||||
set_state preinit
|
||||
trap 'FAILSAFE=true' USR1
|
||||
echo '/sbin/hotplug.failsafe' > /proc/sys/kernel/hotplug
|
||||
|
||||
ifname=eth0
|
||||
|
||||
# hardware specific overrides
|
||||
case "$(cat /proc/diag/model)" in
|
||||
"Linksys WAP54G V1") ifname=eth1;;
|
||||
"ASUS WL-HDD") ifname=eth1;;
|
||||
"ASUS WL-300g") ifname=eth1;;
|
||||
"ASUS (unknown, BCM4702)") ifname=eth1;;
|
||||
esac
|
||||
|
||||
insmod switch-core
|
||||
insmod switch-robo || insmod switch-adm || rmmod switch-core
|
||||
|
||||
ifconfig $ifname 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 up
|
||||
|
||||
[ -d /proc/switch/eth0 ] && {
|
||||
echo 1 > /proc/switch/eth0/reset
|
||||
|
||||
# this would be easier if we blasted the message across all ports
|
||||
# but we don't want packets leaking across interfaces
|
||||
for port in $(seq 0 4); do {
|
||||
echo "$port 5u*" > /proc/switch/eth0/vlan/0/ports
|
||||
netmsg 192.168.1.255 "Press reset now, to enter Failsafe!"
|
||||
}; done
|
||||
} || netmsg 192.168.1.255 "Press reset now, to enter Failsafe!"
|
||||
|
||||
sleep 2
|
||||
|
||||
eval ${FAILSAFE:+failsafe}
|
||||
|
||||
lock -w /tmp/.failsafe
|
||||
set_state preinit
|
||||
echo /sbin/hotplug > /proc/sys/kernel/hotplug
|
||||
|
||||
ifconfig $ifname 0.0.0.0 down
|
||||
|
||||
mount_root
|
||||
exec /sbin/init
|
||||
4
target/linux/brcm-2.4/base-files/sbin/hotplug.failsafe
Executable file
4
target/linux/brcm-2.4/base-files/sbin/hotplug.failsafe
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
case "$1" in
|
||||
button) kill -USR1 1;;
|
||||
esac
|
||||
31
target/linux/brcm-2.4/base-files/sbin/mount_root
Executable file
31
target/linux/brcm-2.4/base-files/sbin/mount_root
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
is_dirty() {
|
||||
grep Broadcom /proc/cpuinfo >&- || return 1
|
||||
OFFSET="$(($(hexdump -v /dev/mtdblock/1 -s 20 -n 2 -e '"%d"')-1))"
|
||||
return $(hexdump -v /dev/mtdblock/1 -s $OFFSET -n 1 -e '"%d"')
|
||||
}
|
||||
|
||||
if [ "$1" != "failsafe" ]; then
|
||||
mtd unlock linux
|
||||
mount | grep jffs2 >&-
|
||||
if [ $? = 0 ] ; then
|
||||
mount -o remount,rw /dev/root /
|
||||
else
|
||||
. /bin/firstboot
|
||||
is_dirty
|
||||
[ $? != 0 ] && {
|
||||
echo "switching to jffs2"
|
||||
mount /dev/mtdblock/4 /jffs -t jffs2
|
||||
fopivot /jffs /rom
|
||||
} || {
|
||||
echo "jffs2 not ready yet; using ramdisk"
|
||||
ramoverlay
|
||||
}
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p /dev/pts
|
||||
mount none /dev/pts -t devpts 2>&-
|
||||
grep sysfs /proc/filesystems >/dev/null && mount -t sysfs none /sys 2>&-
|
||||
133
target/linux/brcm-2.4/src/jffs2root.c
Normal file
133
target/linux/brcm-2.4/src/jffs2root.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* jffs2root.c
|
||||
*
|
||||
* Copyright (C) 2005 Mike Baker
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include "mtd.h"
|
||||
|
||||
#define FILENAME "/dev/mtdblock/1"
|
||||
|
||||
struct trx_header {
|
||||
unsigned magic; /* "HDR0" */
|
||||
unsigned len; /* Length of file including header */
|
||||
unsigned crc32; /* 32-bit CRC from flag_version to end of file */
|
||||
unsigned flag_version; /* 0:15 flags, 16:31 version */
|
||||
unsigned offsets[3]; /* Offsets of partitions from start of header */
|
||||
};
|
||||
|
||||
unsigned long *crc32;
|
||||
|
||||
void init_crc32()
|
||||
{
|
||||
unsigned long crc;
|
||||
unsigned long poly = 0xEDB88320L;
|
||||
int n, bit;
|
||||
if ((crc32 = (unsigned long *) malloc(256 * sizeof(unsigned long))) == (void *)-1) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
for (n = 0; n < 256; n++) {
|
||||
crc = (unsigned long) n;
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
|
||||
crc32[n] = crc;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int crc32buf(char *buf, size_t len)
|
||||
{
|
||||
unsigned int crc = 0xFFFFFFFF;
|
||||
for (; len; len--, buf++)
|
||||
crc = crc32[(crc ^ *buf) & 0xff] ^ (crc >> 8);
|
||||
return crc;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
struct mtd_info_user mtdInfo;
|
||||
unsigned long len;
|
||||
struct trx_header *ptr;
|
||||
char *buf;
|
||||
|
||||
if (((fd = open(FILENAME, O_RDWR)) < 0)
|
||||
|| ((len = lseek(fd, 0, SEEK_END)) < 0)
|
||||
|| ((ptr = (struct trx_header *) mmap(0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == (void *) (-1))
|
||||
|| (ptr->magic != 0x30524448)) {
|
||||
printf("Error reading trx info\n");
|
||||
exit(-1);
|
||||
}
|
||||
close (fd);
|
||||
|
||||
if (((fd = open("/dev/mtd/1", O_RDWR)) < 0)
|
||||
|| (ioctl(fd, MEMGETINFO, &mtdInfo))) {
|
||||
fprintf(stderr, "Could not get MTD device info from %s\n", FILENAME);
|
||||
close(fd);
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (argc > 1 && !strcmp(argv[1],"--move")) {
|
||||
if (ptr->offsets[2] >= ptr->len) {
|
||||
printf("Partition already moved outside trx\n");
|
||||
} else {
|
||||
init_crc32();
|
||||
ptr->offsets[2] += (mtdInfo.erasesize - 1);
|
||||
ptr->offsets[2] &= ~(mtdInfo.erasesize - 1);
|
||||
ptr->len = ptr->offsets[2];
|
||||
ptr->crc32 = crc32buf((void *) &(ptr->flag_version), ptr->len - offsetof(struct trx_header, flag_version));
|
||||
msync(ptr,sizeof(struct trx_header),MS_SYNC|MS_INVALIDATE);
|
||||
printf("Partition moved; please reboot\n");
|
||||
}
|
||||
} else if (argc > 1 && !strcmp(argv[1], "--clean")) {
|
||||
buf = (char *) ptr;
|
||||
if (buf[ptr->offsets[1] - 1] == 0) {
|
||||
init_crc32();
|
||||
buf[ptr->offsets[1] - 1] = 1;
|
||||
ptr->crc32 = crc32buf((void *) &(ptr->flag_version), ptr->len - offsetof(struct trx_header, flag_version));
|
||||
msync(ptr,sizeof(struct trx_header),MS_SYNC|MS_INVALIDATE);
|
||||
printf("Partition marked as clean\n");
|
||||
}
|
||||
} else {
|
||||
int x;
|
||||
printf(" erase: 0x%08x\n",mtdInfo.erasesize);
|
||||
printf("=== trx ===\n");
|
||||
printf("mapped: 0x%08x\n", (unsigned)ptr);
|
||||
printf(" magic: 0x%08x\n", ptr->magic);
|
||||
printf(" len: 0x%08x\n", ptr->len);
|
||||
printf(" crc: 0x%08x\n", ptr->crc32);
|
||||
for (x = 0; x < 3; x++)
|
||||
printf(" offset[%d]: 0x%08x\n", x, ptr->offsets[x]);
|
||||
}
|
||||
|
||||
munmap((void *) ptr, len);
|
||||
return 0;
|
||||
}
|
||||
304
target/linux/brcm-2.4/src/mtd.h
Normal file
304
target/linux/brcm-2.4/src/mtd.h
Normal file
@@ -0,0 +1,304 @@
|
||||
|
||||
/* $Id: mtd.h,v 1.38 2003/01/12 16:30:19 spse Exp $ */
|
||||
|
||||
#ifndef __MTD_MTD_H__
|
||||
#define __MTD_MTD_H__
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mtd/compatmac.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
struct erase_info_user {
|
||||
u_int32_t start;
|
||||
u_int32_t length;
|
||||
};
|
||||
|
||||
struct mtd_oob_buf {
|
||||
u_int32_t start;
|
||||
u_int32_t length;
|
||||
unsigned char *ptr;
|
||||
};
|
||||
|
||||
|
||||
#define MTD_CHAR_MAJOR 90
|
||||
#define MTD_BLOCK_MAJOR 31
|
||||
#define MAX_MTD_DEVICES 16
|
||||
|
||||
|
||||
|
||||
#define MTD_ABSENT 0
|
||||
#define MTD_RAM 1
|
||||
#define MTD_ROM 2
|
||||
#define MTD_NORFLASH 3
|
||||
#define MTD_NANDFLASH 4
|
||||
#define MTD_PEROM 5
|
||||
#define MTD_OTHER 14
|
||||
#define MTD_UNKNOWN 15
|
||||
|
||||
|
||||
|
||||
#define MTD_CLEAR_BITS 1 // Bits can be cleared (flash)
|
||||
#define MTD_SET_BITS 2 // Bits can be set
|
||||
#define MTD_ERASEABLE 4 // Has an erase function
|
||||
#define MTD_WRITEB_WRITEABLE 8 // Direct IO is possible
|
||||
#define MTD_VOLATILE 16 // Set for RAMs
|
||||
#define MTD_XIP 32 // eXecute-In-Place possible
|
||||
#define MTD_OOB 64 // Out-of-band data (NAND flash)
|
||||
#define MTD_ECC 128 // Device capable of automatic ECC
|
||||
|
||||
// Some common devices / combinations of capabilities
|
||||
#define MTD_CAP_ROM 0
|
||||
#define MTD_CAP_RAM (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
|
||||
#define MTD_CAP_NORFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE)
|
||||
#define MTD_CAP_NANDFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB)
|
||||
#define MTD_WRITEABLE (MTD_CLEAR_BITS|MTD_SET_BITS)
|
||||
|
||||
|
||||
// Types of automatic ECC/Checksum available
|
||||
#define MTD_ECC_NONE 0 // No automatic ECC available
|
||||
#define MTD_ECC_RS_DiskOnChip 1 // Automatic ECC on DiskOnChip
|
||||
#define MTD_ECC_SW 2 // SW ECC for Toshiba & Samsung devices
|
||||
|
||||
struct mtd_info_user {
|
||||
u_char type;
|
||||
u_int32_t flags;
|
||||
u_int32_t size; // Total size of the MTD
|
||||
u_int32_t erasesize;
|
||||
u_int32_t oobblock; // Size of OOB blocks (e.g. 512)
|
||||
u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
|
||||
u_int32_t ecctype;
|
||||
u_int32_t eccsize;
|
||||
};
|
||||
|
||||
struct region_info_user {
|
||||
u_int32_t offset; /* At which this region starts,
|
||||
* from the beginning of the MTD */
|
||||
u_int32_t erasesize; /* For this region */
|
||||
u_int32_t numblocks; /* Number of blocks in this region */
|
||||
u_int32_t regionindex;
|
||||
};
|
||||
|
||||
#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
|
||||
#define MEMERASE _IOW('M', 2, struct erase_info_user)
|
||||
#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
|
||||
#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
|
||||
#define MEMLOCK _IOW('M', 5, struct erase_info_user)
|
||||
#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
|
||||
#define MEMGETREGIONCOUNT _IOR('M', 7, int)
|
||||
#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user)
|
||||
#define MEMREADDATA _IOWR('M', 9, struct mtd_oob_buf)
|
||||
#define MEMWRITEDATA _IOWR('M', 10, struct mtd_oob_buf)
|
||||
|
||||
#ifndef __KERNEL__
|
||||
|
||||
typedef struct mtd_info_user mtd_info_t;
|
||||
typedef struct erase_info_user erase_info_t;
|
||||
typedef struct region_info_user region_info_t;
|
||||
|
||||
/* User-space ioctl definitions */
|
||||
|
||||
|
||||
#else /* __KERNEL__ */
|
||||
|
||||
|
||||
#define MTD_ERASE_PENDING 0x01
|
||||
#define MTD_ERASING 0x02
|
||||
#define MTD_ERASE_SUSPEND 0x04
|
||||
#define MTD_ERASE_DONE 0x08
|
||||
#define MTD_ERASE_FAILED 0x10
|
||||
|
||||
struct erase_info {
|
||||
struct mtd_info *mtd;
|
||||
u_int32_t addr;
|
||||
u_int32_t len;
|
||||
u_long time;
|
||||
u_long retries;
|
||||
u_int dev;
|
||||
u_int cell;
|
||||
void (*callback) (struct erase_info *self);
|
||||
u_long priv;
|
||||
u_char state;
|
||||
struct erase_info *next;
|
||||
};
|
||||
|
||||
struct mtd_erase_region_info {
|
||||
u_int32_t offset; /* At which this region starts, from the beginning of the MTD */
|
||||
u_int32_t erasesize; /* For this region */
|
||||
u_int32_t numblocks; /* Number of blocks of erasesize in this region */
|
||||
};
|
||||
|
||||
struct mtd_info {
|
||||
u_char type;
|
||||
u_int32_t flags;
|
||||
u_int32_t size; // Total size of the MTD
|
||||
|
||||
/* "Major" erase size for the device. Na<4E>ve users may take this
|
||||
* to be the only erase size available, or may use the more detailed
|
||||
* information below if they desire
|
||||
*/
|
||||
u_int32_t erasesize;
|
||||
|
||||
u_int32_t oobblock; // Size of OOB blocks (e.g. 512)
|
||||
u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
|
||||
u_int32_t ecctype;
|
||||
u_int32_t eccsize;
|
||||
|
||||
// Kernel-only stuff starts here.
|
||||
char *name;
|
||||
int index;
|
||||
|
||||
/* Data for variable erase regions. If numeraseregions is zero,
|
||||
* it means that the whole device has erasesize as given above.
|
||||
*/
|
||||
int numeraseregions;
|
||||
struct mtd_erase_region_info *eraseregions;
|
||||
|
||||
/* This really shouldn't be here. It can go away in 2.5 */
|
||||
u_int32_t bank_size;
|
||||
|
||||
struct module *module;
|
||||
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
|
||||
|
||||
/* This stuff for eXecute-In-Place */
|
||||
int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
|
||||
|
||||
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
|
||||
void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
|
||||
|
||||
|
||||
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
|
||||
|
||||
int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel);
|
||||
int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel);
|
||||
|
||||
int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
|
||||
|
||||
/*
|
||||
* Methods to access the protection register area, present in some
|
||||
* flash devices. The user data is one time programmable but the
|
||||
* factory data is read only.
|
||||
*/
|
||||
int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
|
||||
int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
|
||||
/* This function is not yet implemented */
|
||||
int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
|
||||
/* iovec-based read/write methods. We need these especially for NAND flash,
|
||||
with its limited number of write cycles per erase.
|
||||
NB: The 'count' parameter is the number of _vectors_, each of
|
||||
which contains an (ofs, len) tuple.
|
||||
*/
|
||||
int (*readv) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, size_t *retlen);
|
||||
int (*readv_ecc) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from,
|
||||
size_t *retlen, u_char *eccbuf, int oobsel);
|
||||
int (*writev) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen);
|
||||
int (*writev_ecc) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to,
|
||||
size_t *retlen, u_char *eccbuf, int oobsel);
|
||||
|
||||
/* Sync */
|
||||
void (*sync) (struct mtd_info *mtd);
|
||||
|
||||
/* Chip-supported device locking */
|
||||
int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
|
||||
int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
|
||||
|
||||
/* Power Management functions */
|
||||
int (*suspend) (struct mtd_info *mtd);
|
||||
void (*resume) (struct mtd_info *mtd);
|
||||
|
||||
struct notifier_block reboot_notifier;
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
|
||||
/* Kernel-side ioctl definitions */
|
||||
|
||||
extern int add_mtd_device(struct mtd_info *mtd);
|
||||
extern int del_mtd_device (struct mtd_info *mtd);
|
||||
|
||||
extern struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num);
|
||||
|
||||
static inline struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
|
||||
{
|
||||
struct mtd_info *ret;
|
||||
|
||||
ret = __get_mtd_device(mtd, num);
|
||||
|
||||
if (ret && ret->module && !try_inc_mod_count(ret->module))
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void put_mtd_device(struct mtd_info *mtd)
|
||||
{
|
||||
if (mtd->module)
|
||||
__MOD_DEC_USE_COUNT(mtd->module);
|
||||
}
|
||||
|
||||
|
||||
struct mtd_notifier {
|
||||
void (*add)(struct mtd_info *mtd);
|
||||
void (*remove)(struct mtd_info *mtd);
|
||||
struct mtd_notifier *next;
|
||||
};
|
||||
|
||||
|
||||
extern void register_mtd_user (struct mtd_notifier *new);
|
||||
extern int unregister_mtd_user (struct mtd_notifier *old);
|
||||
|
||||
int default_mtd_writev(struct mtd_info *mtd, const struct iovec *vecs,
|
||||
unsigned long count, loff_t to, size_t *retlen);
|
||||
|
||||
int default_mtd_readv(struct mtd_info *mtd, struct iovec *vecs,
|
||||
unsigned long count, loff_t from, size_t *retlen);
|
||||
|
||||
#ifndef MTDC
|
||||
#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
|
||||
#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
|
||||
#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
|
||||
#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
|
||||
#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
|
||||
#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args)
|
||||
#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args)
|
||||
#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args)
|
||||
#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
|
||||
#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
|
||||
#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
|
||||
#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0)
|
||||
#endif /* MTDC */
|
||||
|
||||
/*
|
||||
* Debugging macro and defines
|
||||
*/
|
||||
#define MTD_DEBUG_LEVEL0 (0) /* Quiet */
|
||||
#define MTD_DEBUG_LEVEL1 (1) /* Audible */
|
||||
#define MTD_DEBUG_LEVEL2 (2) /* Loud */
|
||||
#define MTD_DEBUG_LEVEL3 (3) /* Noisy */
|
||||
|
||||
#ifdef CONFIG_MTD_DEBUG
|
||||
#define DEBUG(n, args...) \
|
||||
do { \
|
||||
if (n <= CONFIG_MTD_DEBUG_VERBOSE) \
|
||||
printk(KERN_INFO args); \
|
||||
} while(0)
|
||||
#else /* CONFIG_MTD_DEBUG */
|
||||
#define DEBUG(n, args...)
|
||||
#endif /* CONFIG_MTD_DEBUG */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __MTD_MTD_H__ */
|
||||
Reference in New Issue
Block a user