summaryrefslogtreecommitdiff
path: root/package/system/fstools/patches/004-emmc.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/system/fstools/patches/004-emmc.patch')
-rw-r--r--package/system/fstools/patches/004-emmc.patch597
1 files changed, 597 insertions, 0 deletions
diff --git a/package/system/fstools/patches/004-emmc.patch b/package/system/fstools/patches/004-emmc.patch
new file mode 100644
index 0000000..86b8ca7
--- /dev/null
+++ b/package/system/fstools/patches/004-emmc.patch
@@ -0,0 +1,597 @@
+Index: fstools-2015-02-25.1/mount_root.c
+===================================================================
+--- fstools-2015-02-25.1.orig/mount_root.c
++++ fstools-2015-02-25.1/mount_root.c
+@@ -62,6 +62,7 @@ start(int argc, char *argv[1])
+
+ case FS_JFFS2:
+ case FS_UBIFS:
++ case FS_EXT4:
+ mount_overlay(data);
+ break;
+
+@@ -89,6 +90,7 @@ static int
+ done(int argc, char *argv[1])
+ {
+ struct volume *v = volume_find("rootfs_data");
++ FILE * fp = NULL;
+
+ if (!v)
+ return -1;
+@@ -96,6 +98,19 @@ done(int argc, char *argv[1])
+ switch (volume_identify(v)) {
+ case FS_NONE:
+ case FS_DEADCODE:
++ /* if the mtd is created by block2mtd */
++ fp = fopen("/proc/cmdline", "rb");
++ if (fp) {
++ char buf[2048] = {0};
++ fread(buf, 1, sizeof(buf), fp);
++ fclose(fp);
++ buf[sizeof(buf)-1] = 0;
++ if (strstr(buf, "block2mtd")) {
++ fprintf(stderr, "%s is created by block2mtd, ext4_switch.\n", v->name);
++ return ext4_switch(v);
++ }
++ }
++ fprintf(stderr, "%s, normally, jffs2_switch.\n", v->name);
+ return jffs2_switch(v);
+ }
+
+@@ -104,8 +119,11 @@ done(int argc, char *argv[1])
+
+ int main(int argc, char **argv)
+ {
+- if (argc < 2)
++ if (argc < 2) {
++ fprintf(stderr, "%s.\n", argv[0]);
+ return start(argc, argv);
++ }
++ fprintf(stderr, "%s %s.\n", argv[0], argv[1]);
+ if (!strcmp(argv[1], "stop"))
+ return stop(argc, argv);
+ if (!strcmp(argv[1], "done"))
+Index: fstools-2015-02-25.1/libfstools/emmc.c
+===================================================================
+--- /dev/null
++++ fstools-2015-02-25.1/libfstools/emmc.c
+@@ -0,0 +1,272 @@
++/*
++ * Copyright (C) 2015 Hua Shao <nossiac@163.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 2.1
++ * as published by the Free Software Foundation
++ *
++ * 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.
++ */
++
++#include <sys/mount.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <asm/byteorder.h>
++#include <unistd.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <mtd/mtd-user.h>
++
++#include "libfstools.h"
++
++#include "volume.h"
++
++#define PATH_MAX 256
++
++struct emmc_priv {
++ int fd;
++ int idx;
++ char *chr;
++};
++
++static struct driver emmc_driver;
++
++
++static int emmc_partition_load(struct volume *v)
++{
++ struct emmc_priv *p = (struct emmc_priv*) v->priv;
++ struct mtd_info_user mtd_info;
++
++ fprintf(stderr, "%s(%s)\n", __FUNCTION__, v->name);
++ if (p->fd)
++ return 0;
++
++ p->fd = open(p->chr, O_RDWR | O_SYNC);
++ if (p->fd < 0) {
++ p->fd = 0;
++ fprintf(stderr, "Could not open block2mtd device: %s\n", p->chr);
++ return -1;
++ }
++
++ v->type = EMMC;
++
++ if (ioctl(p->fd, MEMGETINFO, &mtd_info)) {
++ close(p->fd);
++ fprintf(stderr, "Could not get MTD device info from %s(block2mtd)\n", p->chr);
++ v->size = 0; // TODO
++ v->block_size = -1; // TODO
++ }
++
++ v->size = mtd_info.size;
++ v->block_size = mtd_info.erasesize;
++
++ return 0;
++}
++
++
++static int block2mtd_find_index(char *name)
++{
++ FILE *fp = fopen("/proc/mtd", "r");
++ static char line[256];
++ char *index = NULL;
++
++ if(!fp)
++ return -1;
++
++ while (!index && fgets(line, sizeof(line), fp)) {
++ char *ret;
++
++ if ((ret = strstr(line, name)) && (ret[strlen(name)] == '"')) {
++ char *eol = strstr(line, ":");
++
++ if (!eol)
++ continue;
++
++ *eol = '\0';
++ index = &line[3];
++ }
++ }
++
++ fclose(fp);
++ if (index)
++ return atoi(index);
++ else
++ return -1;
++}
++
++
++static int emmc_partition_find(struct volume *v, char *name)
++{
++ struct emmc_priv *p;
++ static char buffer[32];
++ FILE * fp = NULL;
++
++ fprintf(stderr, "%s(%p, %s)\n", __FUNCTION__, v, name);
++
++ fp = fopen("/proc/cmdline", "rb");
++ if (fp) {
++ char buf[2048] = {0};
++ fread(buf, 1, sizeof(buf), fp);
++ fclose(fp);
++ buf[sizeof(buf)-1] = 0;
++ if (!strstr(buf, "block2mtd")) {
++ fprintf(stderr, "%s is not created by block2mtd, skip.\n", v->name);
++ return -1;
++ }
++ }
++
++ p = calloc(1, sizeof(struct emmc_priv));
++ if (!p)
++ return -1;
++
++ p->idx = block2mtd_find_index(name);
++
++ v->priv = p;
++ v->name = strdup(name);
++ v->drv = &emmc_driver;
++
++ snprintf(buffer, sizeof(buffer), "/dev/mtdblock%d", p->idx);
++ v->blk = strdup(buffer);
++
++ snprintf(buffer, sizeof(buffer), "/dev/mtd%d", p->idx);
++ p->chr = strdup(buffer);
++
++ if (emmc_partition_load(v)) {
++ fprintf(stderr, "%s emmc_partition_load %s failed\n", __FUNCTION__, v->name);
++ return -1;
++ }
++
++ fprintf(stderr, "v->name = %s\n", v->name);
++ fprintf(stderr, "v->blk = %s\n", v->blk);
++ fprintf(stderr, "v->drv->name = %s\n", v->drv->name);
++ fprintf(stderr, "v->priv->fd = %d\n", p->fd);
++ fprintf(stderr, "v->priv->idx = %d\n", p->idx);
++ fprintf(stderr, "v->priv->chr = %s\n", p->chr);
++
++ return 0;
++}
++
++static int emmc_partition_identify(struct volume *v)
++{
++ struct emmc_priv *p = (struct emmc_priv*) v->priv;
++ __u32 deadc0de;
++ __u16 ext4;
++ size_t sz;
++
++ fprintf(stderr, "%s(%s)\n", __FUNCTION__, v->name);
++ if (emmc_partition_load(v)) {
++ fprintf(stderr, "%s, emmc_partition_load %s failed\n", __FUNCTION__, v->name);
++ return -1;
++ }
++
++ sz = read(p->fd, &deadc0de, sizeof(deadc0de));
++ if (sz != sizeof(deadc0de)) {
++ fprintf(stderr, "%s, reading %s failed: %s\n", __FUNCTION__, v->name, strerror(errno));
++ return -1;
++ }
++
++ deadc0de = __be32_to_cpu(deadc0de);
++ if (deadc0de == 0xdeadc0de) {
++ fprintf(stderr, "ext4 is not ready - marker found\n");
++ return FS_DEADCODE;
++ }
++
++ /* 0x400 -> super block offset in partition
++ 0x38 -> magic offset in superblock
++ */
++ lseek(p->fd, 0x438, SEEK_SET);
++ sz = read(p->fd, &ext4, sizeof(ext4));
++ if (sz != sizeof(ext4)) {
++ fprintf(stderr, "reading %s failed: %s\n", v->name, strerror(errno));
++ return -1;
++ }
++
++ if (ext4 == 0xEF53) {
++ fprintf(stderr, "ext4 is ready\n");
++ return FS_EXT4;
++ }
++
++ fprintf(stderr, "No ext4 magic was found, expected %x, got %x\n", 0xEF53, ext4);
++
++ return FS_NONE;
++}
++
++static int emmc_partition_erase(struct volume *v, int offset, int len)
++{
++ fprintf(stderr, "%s(%s, %d, %d)\n", __FUNCTION__, v->name, offset, len);
++ return 0;
++}
++
++static int emmc_partition_erase_all(struct volume *v)
++{
++ fprintf(stderr, "%s, remove files instead of erase partitions.\n", __FUNCTION__);
++ system("rm -rf /overlay/*");
++ return 0;
++}
++
++static int emmc_partition_init(struct volume *v)
++{
++ fprintf(stderr, "%s(%s)\n", __FUNCTION__, v->name);
++ return 0;
++}
++
++static int emmc_partition_read(struct volume *v, void *buf, int offset, int length)
++{
++ struct emmc_priv *p = (struct emmc_priv*) v->priv;
++
++ fprintf(stderr, "%s(%s, %p, %d, %d)\n", __FUNCTION__, v->name, buf, offset, length);
++ if (emmc_partition_load(v))
++ return -1;
++
++ if (lseek(p->fd, offset, SEEK_SET) == (off_t) -1) {
++ fprintf(stderr, "lseek/read failed\n");
++ return -1;
++ }
++
++ if (read(p->fd, buf, length) == -1) {
++ fprintf(stderr, "read failed\n");
++ return -1;
++ }
++
++ return 0;
++}
++
++static int emmc_partition_write(struct volume *v, void *buf, int offset, int length)
++{
++
++ fprintf(stderr, "%s(%s, %p, %d, %d)\n", __FUNCTION__, v->name, buf, offset, length);
++
++#if 0
++ struct emmc_priv *p = (struct emmc_priv*) v->priv;
++ if (emmc_partition_load(v))
++ return -1;
++
++ if (lseek(p->fd, offset, SEEK_SET) == (off_t) -1) {
++ fprintf(stderr, "lseek/write failed at offset %d\n", offset);
++ perror("lseek");
++ return -1;
++ }
++
++ if (write(p->fd, buf, length) == -1) {
++ fprintf(stderr, "write failed\n");
++ return -1;
++ }
++#endif
++ return 0;
++}
++
++static struct driver emmc_driver = {
++ .name = "emmc",
++ .find = emmc_partition_find,
++ .init = emmc_partition_init,
++ .erase = emmc_partition_erase,
++ .erase_all = emmc_partition_erase_all,
++ .read = emmc_partition_read,
++ .write = emmc_partition_write,
++ .identify = emmc_partition_identify,
++};
++DRIVER(emmc_driver);
+Index: fstools-2015-02-25.1/libfstools/libfstools.h
+===================================================================
+--- fstools-2015-02-25.1.orig/libfstools/libfstools.h
++++ fstools-2015-02-25.1/libfstools/libfstools.h
+@@ -25,6 +25,7 @@ enum {
+ FS_JFFS2,
+ FS_DEADCODE,
+ FS_UBIFS,
++ FS_EXT4,
+ };
+
+ extern char const *extroot_prefix;
+@@ -43,6 +44,7 @@ extern char* find_mount_point(char *bloc
+ extern int find_filesystem(char *fs);
+
+ extern int jffs2_switch(struct volume *v);
++extern int ext4_switch(struct volume *v);
+
+ extern int handle_whiteout(const char *dir);
+ extern void foreachdir(const char *dir, int (*cb)(const char*));
+Index: fstools-2015-02-25.1/libfstools/volume.h
+===================================================================
+--- fstools-2015-02-25.1.orig/libfstools/volume.h
++++ fstools-2015-02-25.1/libfstools/volume.h
+@@ -47,6 +47,7 @@ enum {
+ NANDFLASH,
+ NORFLASH,
+ UBIVOLUME,
++ EMMC,
+ };
+
+ struct volume {
+Index: fstools-2015-02-25.1/libfstools/overlay.c
+===================================================================
+--- fstools-2015-02-25.1.orig/libfstools/overlay.c
++++ fstools-2015-02-25.1/libfstools/overlay.c
+@@ -31,6 +31,7 @@
+ #include "volume.h"
+
+ #define SWITCH_JFFS2 "/tmp/.switch_jffs2"
++#define SWITCH_EXT4 "/tmp/.switch_ext4"
+
+ void
+ foreachdir(const char *dir, int (*cb)(const char*))
+@@ -106,6 +107,59 @@ switch2jffs(struct volume *v)
+ return fopivot("/overlay", "/rom");
+ }
+
++
++static int
++switch2ext4(struct volume *v)
++{
++ struct stat s;
++ int ret;
++
++ if (!stat(SWITCH_EXT4, &s)) {
++ fprintf(stderr, "ext4 switch already running\n");
++ return -1;
++ }
++
++ creat(SWITCH_EXT4, 0600);
++ ret = mount(v->blk, "/rom/overlay", "ext4", MS_NOATIME, NULL);
++ unlink(SWITCH_EXT4);
++ if (ret) {
++ fprintf(stderr, "failed - mount -t ext4 %s /rom/overlay: %s\n", v->blk, strerror(errno));
++
++ char buf[128] = {0};
++ fprintf(stderr, "maybe ext4 is not created yet.\n");
++ snprintf(buf, sizeof(buf), "mkfs.ext4 %s", v->blk);
++ system(buf);
++ fprintf(stderr, "%s.\n", buf);
++
++ creat(SWITCH_EXT4, 0600);
++ ret = mount(v->blk, "/rom/overlay", "ext4", MS_NOATIME, NULL);
++ unlink(SWITCH_EXT4);
++ if (ret) {
++ fprintf(stderr, "failed again, give up - mount -t ext4 %s /rom/overlay: %s\n", v->blk, strerror(errno));
++ return -1;
++ }
++ }
++
++ if (mount("none", "/", NULL, MS_NOATIME | MS_REMOUNT, 0)) {
++ fprintf(stderr, "failed - mount -o remount,ro none: %s\n", strerror(errno));
++ return -1;
++ }
++
++ system("cp -a /tmp/root/* /rom/overlay");
++
++ if (pivot("/rom", "/mnt")) {
++ fprintf(stderr, "failed - pivot /rom /mnt: %s\n", strerror(errno));
++ return -1;
++ }
++
++ if (mount_move("/mnt", "/tmp/root", "")) {
++ fprintf(stderr, "failed - mount -o move /mnt /tmp/root %s\n", strerror(errno));
++ return -1;
++ }
++
++ return fopivot("/overlay", "/rom");
++}
++
+ int
+ handle_whiteout(const char *dir)
+ {
+@@ -199,6 +253,53 @@ jffs2_switch(struct volume *v)
+ return ret;
+ }
+
++int
++ext4_switch(struct volume *v)
++{
++ char *mp;
++ int ret = -1;
++
++ if (find_overlay_mount("overlayfs:/tmp/root"))
++ return -1;
++
++ if (find_filesystem("overlay")) {
++ fprintf(stderr, "overlayfs not found\n");
++ return ret;
++ }
++
++ mp = find_mount_point(v->blk, 0);
++ if (mp) {
++ fprintf(stderr, "rootfs_data:%s is already mounted as %s\n", v->blk, mp);
++ return -1;
++ }
++
++ switch (volume_identify(v)) {
++ case FS_NONE:
++ fprintf(stderr, "no ext4 marker found\n");
++ /* fall through */
++
++ case FS_DEADCODE:
++ ret = switch2ext4(v);
++ if (!ret) {
++ fprintf(stderr, "doing fo cleanup\n");
++ umount2("/tmp/root", MNT_DETACH);
++ foreachdir("/overlay/", handle_whiteout);
++ }
++ break;
++
++ case FS_EXT4:
++ ret = overlay_mount(v, "ext4");
++ if (ret)
++ break;
++ if (mount_move("/tmp", "", "/overlay") || fopivot("/overlay", "/rom")) {
++ fprintf(stderr, "switching to ext4 failed\n");
++ ret = -1;
++ }
++ break;
++ }
++ return ret;
++}
++
+ static int overlay_mount_fs(struct volume *v)
+ {
+ char *fstype;
+@@ -214,12 +315,29 @@ static int overlay_mount_fs(struct volum
+ case FS_UBIFS:
+ fstype = "ubifs";
+ break;
++ case FS_EXT4:
++ fstype = "ext4";
++ break;
+ }
+
+ if (mount(v->blk, "/tmp/overlay", fstype, MS_NOATIME, NULL)) {
+ fprintf(stderr, "failed to mount -t %s %s /tmp/overlay: %s\n",
+ fstype, v->blk, strerror(errno));
+- return -1;
++
++ if (0 == strcmp(fstype, "ext4")) {
++ /* maybe ext4 is not created yet! */
++ char buf[128] = {0};
++ fprintf(stderr, "maybe ext4 is not created yet.\n");
++ snprintf(buf, sizeof(buf), "mkfs.ext4 %s", v->blk);
++ system(buf);
++ fprintf(stderr, "%s.\n", buf);
++
++ if (mount(v->blk, "/tmp/overlay", fstype, MS_NOATIME, NULL)) {
++ fprintf(stderr, "again! failed to mount -t %s %s /tmp/overlay: %s\n",
++ fstype, v->blk, strerror(errno));
++ return -1;
++ }
++ }
+ }
+
+ volume_init(v);
+@@ -250,7 +368,7 @@ int mount_overlay(struct volume *v)
+
+ fprintf(stderr, "switching to overlay\n");
+ if (mount_move("/tmp", "", "/overlay") || fopivot("/overlay", "/rom")) {
+- fprintf(stderr, "switching to jffs2 failed - fallback to ramoverlay\n");
++ fprintf(stderr, "switching to overlay failed - fallback to ramoverlay\n");
+ return ramoverlay();
+ }
+
+Index: fstools-2015-02-25.1/CMakeLists.txt
+===================================================================
+--- fstools-2015-02-25.1.orig/CMakeLists.txt
++++ fstools-2015-02-25.1/CMakeLists.txt
+@@ -10,6 +10,7 @@ ADD_LIBRARY(fstools SHARED
+ libfstools/extroot.c
+ libfstools/overlay.c
+ libfstools/volume.c
++ libfstools/emmc.c
+ libfstools/mtd.c
+ libfstools/mount.c
+ libfstools/ubi.c
+Index: fstools-2015-02-25.1/libfstools/mtd.c
+===================================================================
+--- fstools-2015-02-25.1.orig/libfstools/mtd.c
++++ fstools-2015-02-25.1/libfstools/mtd.c
+@@ -153,10 +153,25 @@ static int mtd_volume_find(struct volume
+ char *idx = mtd_find_index(name);
+ struct mtd_priv *p;
+ char buffer[32];
++ size_t sz;
++ FILE * fp = NULL;
+
+ if (!idx)
+ return -1;
+
++ /* if the mtd is created by block2mtd */
++ fp = fopen("/proc/cmdline", "rb");
++ if (fp) {
++ char buf[2048] = {0};
++ sz = fread(buf, 1, sizeof(buf), fp);
++ fclose(fp);
++ buf[sizeof(buf)-1] = 0;
++ if (strstr(buf, "block2mtd")) {
++ fprintf(stderr, "%s, %s is created by block2mtd.\n", __FUNCTION__, name);
++ return -1;
++ }
++ }
++
+ p = calloc(1, sizeof(struct mtd_priv));
+ if (!p)
+ return -1;
+@@ -186,12 +201,26 @@ static int mtd_volume_identify(struct vo
+ __u32 deadc0de;
+ __u16 jffs2;
+ size_t sz;
++ FILE * fp = NULL;
+
+ if (mtd_volume_load(v)) {
+ fprintf(stderr, "reading %s failed\n", v->name);
+ return -1;
+ }
+
++ /* if the mtd is created by block2mtd */
++ fp = fopen("/proc/cmdline", "rb");
++ if (fp) {
++ char buf[2048] = {0};
++ sz = fread(buf, 1, sizeof(buf), fp);
++ fclose(fp);
++ buf[sizeof(buf)-1] = 0;
++ if (strstr(buf, "block2mtd")) {
++ fprintf(stderr, "%s, %s is created by block2mtd, default use FS_EXT4.\n", __FUNCTION__, v->name);
++ return FS_EXT4;
++ }
++ }
++
+ sz = read(p->fd, &deadc0de, sizeof(deadc0de));
+
+ if (sz != sizeof(deadc0de)) {