Merge branch 'rmobile' of git://git.denx.de/u-boot-sh
[oweals/u-boot.git] / fs / ext4 / ext4_write.c
index 0c1f62b60caf5d1ab82c2a5800700b14481e744f..e027916763f9b52937c7fe13f1698b67b94eb901 100644 (file)
  *
  * ext4write : Based on generic ext4 protocol.
  *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 
 #include <common.h>
+#include <memalign.h>
 #include <linux/stat.h>
 #include <div64.h>
 #include "ext4_common.h"
@@ -52,18 +41,18 @@ static void ext4fs_update(void)
        /* update block groups */
        for (i = 0; i < fs->no_blkgrp; i++) {
                fs->bgd[i].bg_checksum = ext4fs_checksum_update(i);
-               put_ext4((uint64_t)(fs->bgd[i].block_id * fs->blksz),
+               put_ext4((uint64_t)((uint64_t)fs->bgd[i].block_id * (uint64_t)fs->blksz),
                         fs->blk_bmaps[i], fs->blksz);
        }
 
        /* update inode table groups */
        for (i = 0; i < fs->no_blkgrp; i++) {
-               put_ext4((uint64_t) (fs->bgd[i].inode_id * fs->blksz),
+               put_ext4((uint64_t) ((uint64_t)fs->bgd[i].inode_id * (uint64_t)fs->blksz),
                         fs->inode_bmaps[i], fs->blksz);
        }
 
        /* update the block group descriptor table */
-       put_ext4((uint64_t)(fs->gdtable_blkno * fs->blksz),
+       put_ext4((uint64_t)((uint64_t)fs->gdtable_blkno * (uint64_t)fs->blksz),
                 (struct ext2_block_group *)fs->gdtable,
                 (fs->blksz * fs->no_blk_pergdt));
 
@@ -88,8 +77,8 @@ int ext4fs_get_bgdtable(void)
        if (!fs->gdtable)
                return -ENOMEM;
        /* read the group descriptor table */
-       status = ext4fs_devread(fs->gdtable_blkno * fs->sect_perblk, 0,
-                               fs->blksz * fs->no_blk_pergdt, fs->gdtable);
+       status = ext4fs_devread((lbaint_t)fs->gdtable_blkno * fs->sect_perblk,
+                               0, fs->blksz * fs->no_blk_pergdt, fs->gdtable);
        if (status == 0)
                goto fail;
 
@@ -128,10 +117,8 @@ static void delete_single_indirect_block(struct ext2_inode *inode)
        if (inode->b.blocks.indir_block != 0) {
                debug("SIPB releasing %u\n", inode->b.blocks.indir_block);
                blknr = inode->b.blocks.indir_block;
-               if (fs->blksz != 1024) {
-                       bg_idx = blknr / blk_per_grp;
-               } else {
-                       bg_idx = blknr / blk_per_grp;
+               bg_idx = blknr / blk_per_grp;
+               if (fs->blksz == 1024) {
                        remainder = blknr % blk_per_grp;
                        if (!remainder)
                                bg_idx--;
@@ -142,7 +129,7 @@ static void delete_single_indirect_block(struct ext2_inode *inode)
                /* journal backup */
                if (prev_bg_bmap_idx != bg_idx) {
                        status =
-                           ext4fs_devread(bgd[bg_idx].block_id *
+                           ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
                                           fs->sect_perblk, 0, fs->blksz,
                                           journal_buffer);
                        if (status == 0)
@@ -186,18 +173,16 @@ static void delete_double_indirect_block(struct ext2_inode *inode)
                }
                DIB_start_addr = (unsigned int *)di_buffer;
                blknr = inode->b.blocks.double_indir_block;
-               status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
-                                       (char *)di_buffer);
+               status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
+                                       fs->blksz, (char *)di_buffer);
                for (i = 0; i < fs->blksz / sizeof(int); i++) {
                        if (*di_buffer == 0)
                                break;
 
                        debug("DICB releasing %u\n", *di_buffer);
-                       if (fs->blksz != 1024) {
-                               bg_idx = (*di_buffer) / blk_per_grp;
-                       } else {
-                               bg_idx = (*di_buffer) / blk_per_grp;
-                               remainder = (*di_buffer) % blk_per_grp;
+                       bg_idx = *di_buffer / blk_per_grp;
+                       if (fs->blksz == 1024) {
+                               remainder = *di_buffer % blk_per_grp;
                                if (!remainder)
                                        bg_idx--;
                        }
@@ -208,7 +193,8 @@ static void delete_double_indirect_block(struct ext2_inode *inode)
                        fs->sb->free_blocks++;
                        /* journal backup */
                        if (prev_bg_bmap_idx != bg_idx) {
-                               status = ext4fs_devread(bgd[bg_idx].block_id
+                               status = ext4fs_devread((lbaint_t)
+                                                       bgd[bg_idx].block_id
                                                        * fs->sect_perblk, 0,
                                                        fs->blksz,
                                                        journal_buffer);
@@ -224,10 +210,8 @@ static void delete_double_indirect_block(struct ext2_inode *inode)
 
                /* removing the parent double indirect block */
                blknr = inode->b.blocks.double_indir_block;
-               if (fs->blksz != 1024) {
-                       bg_idx = blknr / blk_per_grp;
-               } else {
-                       bg_idx = blknr / blk_per_grp;
+               bg_idx = blknr / blk_per_grp;
+               if (fs->blksz == 1024) {
                        remainder = blknr % blk_per_grp;
                        if (!remainder)
                                bg_idx--;
@@ -238,7 +222,7 @@ static void delete_double_indirect_block(struct ext2_inode *inode)
                /* journal backup */
                if (prev_bg_bmap_idx != bg_idx) {
                        memset(journal_buffer, '\0', fs->blksz);
-                       status = ext4fs_devread(bgd[bg_idx].block_id *
+                       status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
                                                fs->sect_perblk, 0, fs->blksz,
                                                journal_buffer);
                        if (status == 0)
@@ -287,8 +271,8 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                }
                tib_start_addr = (unsigned int *)tigp_buffer;
                blknr = inode->b.blocks.triple_indir_block;
-               status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
-                                       (char *)tigp_buffer);
+               status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
+                                       fs->blksz, (char *)tigp_buffer);
                for (i = 0; i < fs->blksz / sizeof(int); i++) {
                        if (*tigp_buffer == 0)
                                break;
@@ -298,18 +282,15 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                        if (!tip_buffer)
                                goto fail;
                        tipb_start_addr = (unsigned int *)tip_buffer;
-                       status = ext4fs_devread((*tigp_buffer) *
+                       status = ext4fs_devread((lbaint_t)(*tigp_buffer) *
                                                fs->sect_perblk, 0, fs->blksz,
                                                (char *)tip_buffer);
                        for (j = 0; j < fs->blksz / sizeof(int); j++) {
                                if (*tip_buffer == 0)
                                        break;
-                               if (fs->blksz != 1024) {
-                                       bg_idx = (*tip_buffer) / blk_per_grp;
-                               } else {
-                                       bg_idx = (*tip_buffer) / blk_per_grp;
-
-                                       remainder = (*tip_buffer) % blk_per_grp;
+                               bg_idx = *tip_buffer / blk_per_grp;
+                               if (fs->blksz == 1024) {
+                                       remainder = *tip_buffer % blk_per_grp;
                                        if (!remainder)
                                                bg_idx--;
                                }
@@ -325,6 +306,7 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                                if (prev_bg_bmap_idx != bg_idx) {
                                        status =
                                            ext4fs_devread(
+                                                       (lbaint_t)
                                                        bgd[bg_idx].block_id *
                                                        fs->sect_perblk, 0,
                                                        fs->blksz,
@@ -346,12 +328,9 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                         * removing the grand parent blocks
                         * which is connected to inode
                         */
-                       if (fs->blksz != 1024) {
-                               bg_idx = (*tigp_buffer) / blk_per_grp;
-                       } else {
-                               bg_idx = (*tigp_buffer) / blk_per_grp;
-
-                               remainder = (*tigp_buffer) % blk_per_grp;
+                       bg_idx = *tigp_buffer / blk_per_grp;
+                       if (fs->blksz == 1024) {
+                               remainder = *tigp_buffer % blk_per_grp;
                                if (!remainder)
                                        bg_idx--;
                        }
@@ -365,7 +344,8 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                        if (prev_bg_bmap_idx != bg_idx) {
                                memset(journal_buffer, '\0', fs->blksz);
                                status =
-                                   ext4fs_devread(bgd[bg_idx].block_id *
+                                   ext4fs_devread((lbaint_t)
+                                                  bgd[bg_idx].block_id *
                                                   fs->sect_perblk, 0,
                                                   fs->blksz, journal_buffer);
                                if (status == 0)
@@ -380,10 +360,8 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
 
                /* removing the grand parent triple indirect block */
                blknr = inode->b.blocks.triple_indir_block;
-               if (fs->blksz != 1024) {
-                       bg_idx = blknr / blk_per_grp;
-               } else {
-                       bg_idx = blknr / blk_per_grp;
+               bg_idx = blknr / blk_per_grp;
+               if (fs->blksz == 1024) {
                        remainder = blknr % blk_per_grp;
                        if (!remainder)
                                bg_idx--;
@@ -394,7 +372,7 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                /* journal backup */
                if (prev_bg_bmap_idx != bg_idx) {
                        memset(journal_buffer, '\0', fs->blksz);
-                       status = ext4fs_devread(bgd[bg_idx].block_id *
+                       status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
                                                fs->sect_perblk, 0, fs->blksz,
                                                journal_buffer);
                        if (status == 0)
@@ -461,10 +439,8 @@ static int ext4fs_delete_file(int inodeno)
 
                for (i = 0; i < no_blocks; i++) {
                        blknr = read_allocated_block(&(node_inode->inode), i);
-                       if (fs->blksz != 1024) {
-                               bg_idx = blknr / blk_per_grp;
-                       } else {
-                               bg_idx = blknr / blk_per_grp;
+                       bg_idx = blknr / blk_per_grp;
+                       if (fs->blksz == 1024) {
                                remainder = blknr % blk_per_grp;
                                if (!remainder)
                                        bg_idx--;
@@ -480,7 +456,8 @@ static int ext4fs_delete_file(int inodeno)
                        /* journal backup */
                        if (prev_bg_bmap_idx != bg_idx) {
                                status =
-                                   ext4fs_devread(bgd[bg_idx].block_id *
+                                   ext4fs_devread((lbaint_t)
+                                                  bgd[bg_idx].block_id *
                                                   fs->sect_perblk, 0,
                                                   fs->blksz, journal_buffer);
                                if (status == 0)
@@ -507,10 +484,8 @@ static int ext4fs_delete_file(int inodeno)
                        no_blocks++;
                for (i = 0; i < no_blocks; i++) {
                        blknr = read_allocated_block(&inode, i);
-                       if (fs->blksz != 1024) {
-                               bg_idx = blknr / blk_per_grp;
-                       } else {
-                               bg_idx = blknr / blk_per_grp;
+                       bg_idx = blknr / blk_per_grp;
+                       if (fs->blksz == 1024) {
                                remainder = blknr % blk_per_grp;
                                if (!remainder)
                                        bg_idx--;
@@ -524,7 +499,8 @@ static int ext4fs_delete_file(int inodeno)
                        /* journal backup */
                        if (prev_bg_bmap_idx != bg_idx) {
                                memset(journal_buffer, '\0', fs->blksz);
-                               status = ext4fs_devread(bgd[bg_idx].block_id
+                               status = ext4fs_devread((lbaint_t)
+                                                       bgd[bg_idx].block_id
                                                        * fs->sect_perblk,
                                                        0, fs->blksz,
                                                        journal_buffer);
@@ -555,7 +531,7 @@ static int ext4fs_delete_file(int inodeno)
        if (!read_buffer)
                goto fail;
        start_block_address = read_buffer;
-       status = ext4fs_devread(blkno * fs->sect_perblk,
+       status = ext4fs_devread((lbaint_t)blkno * fs->sect_perblk,
                                0, fs->blksz, read_buffer);
        if (status == 0)
                goto fail;
@@ -578,7 +554,7 @@ static int ext4fs_delete_file(int inodeno)
        fs->sb->free_inodes++;
        /* journal backup */
        memset(journal_buffer, '\0', fs->blksz);
-       status = ext4fs_devread(bgd[ibmap_idx].inode_id *
+       status = ext4fs_devread((lbaint_t)bgd[ibmap_idx].inode_id *
                                fs->sect_perblk, 0, fs->blksz, journal_buffer);
        if (status == 0)
                goto fail;
@@ -587,6 +563,7 @@ static int ext4fs_delete_file(int inodeno)
 
        ext4fs_update();
        ext4fs_deinit();
+       ext4fs_reinit_global();
 
        if (ext4fs_init() != 0) {
                printf("error in File System init\n");
@@ -653,7 +630,8 @@ int ext4fs_init(void)
 
        for (i = 0; i < fs->no_blkgrp; i++) {
                status =
-                   ext4fs_devread(fs->bgd[i].block_id * fs->sect_perblk, 0,
+                   ext4fs_devread((lbaint_t)fs->bgd[i].block_id *
+                                  fs->sect_perblk, 0,
                                   fs->blksz, (char *)fs->blk_bmaps[i]);
                if (status == 0)
                        goto fail;
@@ -670,7 +648,8 @@ int ext4fs_init(void)
        }
 
        for (i = 0; i < fs->no_blkgrp; i++) {
-               status = ext4fs_devread(fs->bgd[i].inode_id * fs->sect_perblk,
+               status = ext4fs_devread((lbaint_t)fs->bgd[i].inode_id *
+                                       fs->sect_perblk,
                                        0, fs->blksz,
                                        (char *)fs->inode_bmaps[i]);
                if (status == 0)
@@ -710,11 +689,11 @@ void ext4fs_deinit(void)
                                  &inode_journal);
                blknr = read_allocated_block(&inode_journal,
                                        EXT2_JOURNAL_SUPERBLOCK);
-               ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
+               ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
                               temp_buff);
                jsb = (struct journal_superblock_t *)temp_buff;
                jsb->s_start = cpu_to_be32(0);
-               put_ext4((uint64_t) (blknr * fs->blksz),
+               put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
                         (struct journal_superblock_t *)temp_buff, fs->blksz);
                free(temp_buff);
        }
@@ -798,7 +777,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
                                        delayed_next += blockend >> log2blksz;
                                } else {        /* spill */
                                        put_ext4((uint64_t)
-                                                (delayed_start << log2blksz),
+                                                ((uint64_t)delayed_start << log2blksz),
                                                 delayed_buf,
                                                 (uint32_t) delayed_extent);
                                        previous_block_number = blknr;
@@ -819,7 +798,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
                } else {
                        if (previous_block_number != -1) {
                                /* spill */
-                               put_ext4((uint64_t) (delayed_start <<
+                               put_ext4((uint64_t) ((uint64_t)delayed_start <<
                                                     log2blksz),
                                         delayed_buf,
                                         (uint32_t) delayed_extent);
@@ -831,7 +810,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
        }
        if (previous_block_number != -1) {
                /* spill */
-               put_ext4((uint64_t) (delayed_start << log2blksz),
+               put_ext4((uint64_t) ((uint64_t)delayed_start << log2blksz),
                         delayed_buf, (uint32_t) delayed_extent);
                previous_block_number = -1;
        }
@@ -862,7 +841,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
        unsigned int ibmap_idx;
        struct ext_filesystem *fs = get_fs();
        ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256);
-       memset(filename, 0x00, sizeof(filename));
+       memset(filename, 0x00, 256);
 
        g_parent_inode = zalloc(sizeof(struct ext2_inode));
        if (!g_parent_inode)
@@ -934,7 +913,8 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
                        (inodeno % __le32_to_cpu(sblock->inodes_per_group)) /
                        inodes_per_block;
        blkoff = (inodeno % inodes_per_block) * fs->inodesz;
-       ext4fs_devread(itable_blkno * fs->sect_perblk, 0, fs->blksz, temp_ptr);
+       ext4fs_devread((lbaint_t)itable_blkno * fs->sect_perblk, 0, fs->blksz,
+                      temp_ptr);
        if (ext4fs_log_journal(temp_ptr, itable_blkno))
                goto fail;
 
@@ -954,7 +934,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
        blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz;
        if (parent_itable_blkno != itable_blkno) {
                memset(temp_ptr, '\0', fs->blksz);
-               ext4fs_devread(parent_itable_blkno * fs->sect_perblk,
+               ext4fs_devread((lbaint_t)parent_itable_blkno * fs->sect_perblk,
                               0, fs->blksz, temp_ptr);
                if (ext4fs_log_journal(temp_ptr, parent_itable_blkno))
                        goto fail;
@@ -996,3 +976,29 @@ fail:
 
        return -1;
 }
+
+int ext4_write_file(const char *filename, void *buf, loff_t offset,
+                   loff_t len, loff_t *actwrite)
+{
+       int ret;
+
+       if (offset != 0) {
+               printf("** Cannot support non-zero offset **\n");
+               return -1;
+       }
+
+       ret = ext4fs_write(filename, buf, len);
+       if (ret) {
+               printf("** Error ext4fs_write() **\n");
+               goto fail;
+       }
+
+       *actwrite = len;
+
+       return 0;
+
+fail:
+       *actwrite = 0;
+
+       return -1;
+}