Commit 04735e9c5578dd4f3584be5454b9779e8e5c2af9

Authored by Frederic Leroy
Committed by Tom Rini
1 parent 0eb33ad253

Fix ext2/ext4 filesystem accesses beyond 2TiB

With CONFIG_SYS_64BIT_LBA, lbaint_t gets defined as a 64-bit type,
which is required to represent block numbers for storage devices that
exceed 2TiB (the block size usually is 512B), e.g. recent hard drives

We now use lbaint_t for partition offset to reflect the lbaint_t change,
and access partitions beyond or crossing the 2.1TiB limit.
This required changes to signature of ext4fs_devread(), and type of all
variables relatives to block sector.

ext2/ext4 fs uses logical block represented by a 32 bit value. Logical
block is a multiple of device block sector. To avoid overflow problem
when calling ext4fs_devread(), we need to cast the sector parameter.

Signed-off-by: Frédéric Leroy <fredo@starox.org>

Showing 12 changed files with 93 additions and 70 deletions Inline Diff

1 /* 1 /*
2 * (C) Copyright 2000-2011 2 * (C) Copyright 2000-2011
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 * 4 *
5 * See file CREDITS for list of people who contributed to this 5 * See file CREDITS for list of people who contributed to this
6 * project. 6 * project.
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of 10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version. 11 * the License, or (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA 21 * MA 02111-1307 USA
22 * 22 *
23 */ 23 */
24 #include <common.h> 24 #include <common.h>
25 #include <command.h> 25 #include <command.h>
26 #include <part.h> 26 #include <part.h>
27 27
28 #if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \ 28 #if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \
29 defined(CONFIG_USB_STORAGE) 29 defined(CONFIG_USB_STORAGE)
30 int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, 30 int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
31 char *const argv[]) 31 char *const argv[])
32 { 32 {
33 int dev, part; 33 int dev, part;
34 ulong addr = CONFIG_SYS_LOAD_ADDR; 34 ulong addr = CONFIG_SYS_LOAD_ADDR;
35 ulong cnt; 35 ulong cnt;
36 disk_partition_t info; 36 disk_partition_t info;
37 image_header_t *hdr; 37 image_header_t *hdr;
38 block_dev_desc_t *dev_desc; 38 block_dev_desc_t *dev_desc;
39 39
40 #if defined(CONFIG_FIT) 40 #if defined(CONFIG_FIT)
41 const void *fit_hdr = NULL; 41 const void *fit_hdr = NULL;
42 #endif 42 #endif
43 43
44 bootstage_mark(BOOTSTAGE_ID_IDE_START); 44 bootstage_mark(BOOTSTAGE_ID_IDE_START);
45 if (argc > 3) { 45 if (argc > 3) {
46 bootstage_error(BOOTSTAGE_ID_IDE_ADDR); 46 bootstage_error(BOOTSTAGE_ID_IDE_ADDR);
47 return CMD_RET_USAGE; 47 return CMD_RET_USAGE;
48 } 48 }
49 bootstage_mark(BOOTSTAGE_ID_IDE_ADDR); 49 bootstage_mark(BOOTSTAGE_ID_IDE_ADDR);
50 50
51 if (argc > 1) 51 if (argc > 1)
52 addr = simple_strtoul(argv[1], NULL, 16); 52 addr = simple_strtoul(argv[1], NULL, 16);
53 53
54 bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE); 54 bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
55 55
56 part = get_device_and_partition(intf, (argc == 3) ? argv[2] : NULL, 56 part = get_device_and_partition(intf, (argc == 3) ? argv[2] : NULL,
57 &dev_desc, &info, 1); 57 &dev_desc, &info, 1);
58 if (part < 0) { 58 if (part < 0) {
59 bootstage_error(BOOTSTAGE_ID_IDE_TYPE); 59 bootstage_error(BOOTSTAGE_ID_IDE_TYPE);
60 return 1; 60 return 1;
61 } 61 }
62 62
63 dev = dev_desc->dev; 63 dev = dev_desc->dev;
64 bootstage_mark(BOOTSTAGE_ID_IDE_TYPE); 64 bootstage_mark(BOOTSTAGE_ID_IDE_TYPE);
65 65
66 printf("\nLoading from %s device %d, partition %d: " 66 printf("\nLoading from %s device %d, partition %d: "
67 "Name: %.32s Type: %.32s\n", intf, dev, part, info.name, 67 "Name: %.32s Type: %.32s\n", intf, dev, part, info.name,
68 info.type); 68 info.type);
69 69
70 debug("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", 70 debug("First Block: " LBAFU ", # of blocks: " LBAFU
71 ", Block Size: %ld\n",
71 info.start, info.size, info.blksz); 72 info.start, info.size, info.blksz);
72 73
73 if (dev_desc->block_read(dev, info.start, 1, (ulong *) addr) != 1) { 74 if (dev_desc->block_read(dev, info.start, 1, (ulong *) addr) != 1) {
74 printf("** Read error on %d:%d\n", dev, part); 75 printf("** Read error on %d:%d\n", dev, part);
75 bootstage_error(BOOTSTAGE_ID_IDE_PART_READ); 76 bootstage_error(BOOTSTAGE_ID_IDE_PART_READ);
76 return 1; 77 return 1;
77 } 78 }
78 bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ); 79 bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ);
79 80
80 switch (genimg_get_format((void *) addr)) { 81 switch (genimg_get_format((void *) addr)) {
81 case IMAGE_FORMAT_LEGACY: 82 case IMAGE_FORMAT_LEGACY:
82 hdr = (image_header_t *) addr; 83 hdr = (image_header_t *) addr;
83 84
84 bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT); 85 bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT);
85 86
86 if (!image_check_hcrc(hdr)) { 87 if (!image_check_hcrc(hdr)) {
87 puts("\n** Bad Header Checksum **\n"); 88 puts("\n** Bad Header Checksum **\n");
88 bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM); 89 bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM);
89 return 1; 90 return 1;
90 } 91 }
91 bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM); 92 bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM);
92 93
93 image_print_contents(hdr); 94 image_print_contents(hdr);
94 95
95 cnt = image_get_image_size(hdr); 96 cnt = image_get_image_size(hdr);
96 break; 97 break;
97 #if defined(CONFIG_FIT) 98 #if defined(CONFIG_FIT)
98 case IMAGE_FORMAT_FIT: 99 case IMAGE_FORMAT_FIT:
99 fit_hdr = (const void *) addr; 100 fit_hdr = (const void *) addr;
100 puts("Fit image detected...\n"); 101 puts("Fit image detected...\n");
101 102
102 cnt = fit_get_size(fit_hdr); 103 cnt = fit_get_size(fit_hdr);
103 break; 104 break;
104 #endif 105 #endif
105 default: 106 default:
106 bootstage_error(BOOTSTAGE_ID_IDE_FORMAT); 107 bootstage_error(BOOTSTAGE_ID_IDE_FORMAT);
107 puts("** Unknown image type\n"); 108 puts("** Unknown image type\n");
108 return 1; 109 return 1;
109 } 110 }
110 111
111 cnt += info.blksz - 1; 112 cnt += info.blksz - 1;
112 cnt /= info.blksz; 113 cnt /= info.blksz;
113 cnt -= 1; 114 cnt -= 1;
114 115
115 if (dev_desc->block_read(dev, info.start + 1, cnt, 116 if (dev_desc->block_read(dev, info.start + 1, cnt,
116 (ulong *)(addr + info.blksz)) != cnt) { 117 (ulong *)(addr + info.blksz)) != cnt) {
117 printf("** Read error on %d:%d\n", dev, part); 118 printf("** Read error on %d:%d\n", dev, part);
118 bootstage_error(BOOTSTAGE_ID_IDE_READ); 119 bootstage_error(BOOTSTAGE_ID_IDE_READ);
119 return 1; 120 return 1;
120 } 121 }
121 bootstage_mark(BOOTSTAGE_ID_IDE_READ); 122 bootstage_mark(BOOTSTAGE_ID_IDE_READ);
122 123
123 #if defined(CONFIG_FIT) 124 #if defined(CONFIG_FIT)
124 /* This cannot be done earlier, 125 /* This cannot be done earlier,
125 * we need complete FIT image in RAM first */ 126 * we need complete FIT image in RAM first */
126 if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) { 127 if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) {
127 if (!fit_check_format(fit_hdr)) { 128 if (!fit_check_format(fit_hdr)) {
128 bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ); 129 bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ);
129 puts("** Bad FIT image format\n"); 130 puts("** Bad FIT image format\n");
130 return 1; 131 return 1;
131 } 132 }
132 bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK); 133 bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK);
133 fit_print_contents(fit_hdr); 134 fit_print_contents(fit_hdr);
134 } 135 }
135 #endif 136 #endif
136 137
137 flush_cache(addr, (cnt+1)*info.blksz); 138 flush_cache(addr, (cnt+1)*info.blksz);
138 139
139 /* Loading ok, update default load address */ 140 /* Loading ok, update default load address */
140 load_addr = addr; 141 load_addr = addr;
141 142
142 return bootm_maybe_autostart(cmdtp, argv[0]); 143 return bootm_maybe_autostart(cmdtp, argv[0]);
143 } 144 }
144 #endif 145 #endif
145 146
1 /* 1 /*
2 * Copyright (C) 2008 RuggedCom, Inc. 2 * Copyright (C) 2008 RuggedCom, Inc.
3 * Richard Retanubun <RichardRetanubun@RuggedCom.com> 3 * Richard Retanubun <RichardRetanubun@RuggedCom.com>
4 * 4 *
5 * See file CREDITS for list of people who contributed to this 5 * See file CREDITS for list of people who contributed to this
6 * project. 6 * project.
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of 10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version. 11 * the License, or (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA 21 * MA 02111-1307 USA
22 */ 22 */
23 23
24 /* 24 /*
25 * Problems with CONFIG_SYS_64BIT_LBA: 25 * Problems with CONFIG_SYS_64BIT_LBA:
26 * 26 *
27 * struct disk_partition.start in include/part.h is sized as ulong. 27 * struct disk_partition.start in include/part.h is sized as ulong.
28 * When CONFIG_SYS_64BIT_LBA is activated, lbaint_t changes from ulong to uint64_t. 28 * When CONFIG_SYS_64BIT_LBA is activated, lbaint_t changes from ulong to uint64_t.
29 * For now, it is cast back to ulong at assignment. 29 * For now, it is cast back to ulong at assignment.
30 * 30 *
31 * This limits the maximum size of addressable storage to < 2 Terra Bytes 31 * This limits the maximum size of addressable storage to < 2 Terra Bytes
32 */ 32 */
33 #include <asm/unaligned.h> 33 #include <asm/unaligned.h>
34 #include <common.h> 34 #include <common.h>
35 #include <command.h> 35 #include <command.h>
36 #include <ide.h> 36 #include <ide.h>
37 #include <malloc.h> 37 #include <malloc.h>
38 #include <part_efi.h> 38 #include <part_efi.h>
39 #include <linux/ctype.h> 39 #include <linux/ctype.h>
40 40
41 DECLARE_GLOBAL_DATA_PTR; 41 DECLARE_GLOBAL_DATA_PTR;
42 42
43 #ifdef HAVE_BLOCK_DEVICE 43 #ifdef HAVE_BLOCK_DEVICE
44 /** 44 /**
45 * efi_crc32() - EFI version of crc32 function 45 * efi_crc32() - EFI version of crc32 function
46 * @buf: buffer to calculate crc32 of 46 * @buf: buffer to calculate crc32 of
47 * @len - length of buf 47 * @len - length of buf
48 * 48 *
49 * Description: Returns EFI-style CRC32 value for @buf 49 * Description: Returns EFI-style CRC32 value for @buf
50 */ 50 */
51 static inline u32 efi_crc32(const void *buf, u32 len) 51 static inline u32 efi_crc32(const void *buf, u32 len)
52 { 52 {
53 return crc32(0, buf, len); 53 return crc32(0, buf, len);
54 } 54 }
55 55
56 /* 56 /*
57 * Private function prototypes 57 * Private function prototypes
58 */ 58 */
59 59
60 static int pmbr_part_valid(struct partition *part); 60 static int pmbr_part_valid(struct partition *part);
61 static int is_pmbr_valid(legacy_mbr * mbr); 61 static int is_pmbr_valid(legacy_mbr * mbr);
62 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, 62 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
63 gpt_header * pgpt_head, gpt_entry ** pgpt_pte); 63 gpt_header * pgpt_head, gpt_entry ** pgpt_pte);
64 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, 64 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
65 gpt_header * pgpt_head); 65 gpt_header * pgpt_head);
66 static int is_pte_valid(gpt_entry * pte); 66 static int is_pte_valid(gpt_entry * pte);
67 67
68 static char *print_efiname(gpt_entry *pte) 68 static char *print_efiname(gpt_entry *pte)
69 { 69 {
70 static char name[PARTNAME_SZ + 1]; 70 static char name[PARTNAME_SZ + 1];
71 int i; 71 int i;
72 for (i = 0; i < PARTNAME_SZ; i++) { 72 for (i = 0; i < PARTNAME_SZ; i++) {
73 u8 c; 73 u8 c;
74 c = pte->partition_name[i] & 0xff; 74 c = pte->partition_name[i] & 0xff;
75 c = (c && !isprint(c)) ? '.' : c; 75 c = (c && !isprint(c)) ? '.' : c;
76 name[i] = c; 76 name[i] = c;
77 } 77 }
78 name[PARTNAME_SZ] = 0; 78 name[PARTNAME_SZ] = 0;
79 return name; 79 return name;
80 } 80 }
81 81
82 static void uuid_string(unsigned char *uuid, char *str) 82 static void uuid_string(unsigned char *uuid, char *str)
83 { 83 {
84 static const u8 le[16] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 84 static const u8 le[16] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11,
85 12, 13, 14, 15}; 85 12, 13, 14, 15};
86 int i; 86 int i;
87 87
88 for (i = 0; i < 16; i++) { 88 for (i = 0; i < 16; i++) {
89 sprintf(str, "%02x", uuid[le[i]]); 89 sprintf(str, "%02x", uuid[le[i]]);
90 str += 2; 90 str += 2;
91 switch (i) { 91 switch (i) {
92 case 3: 92 case 3:
93 case 5: 93 case 5:
94 case 7: 94 case 7:
95 case 9: 95 case 9:
96 *str++ = '-'; 96 *str++ = '-';
97 break; 97 break;
98 } 98 }
99 } 99 }
100 } 100 }
101 101
102 static efi_guid_t system_guid = PARTITION_SYSTEM_GUID; 102 static efi_guid_t system_guid = PARTITION_SYSTEM_GUID;
103 103
104 static inline int is_bootable(gpt_entry *p) 104 static inline int is_bootable(gpt_entry *p)
105 { 105 {
106 return p->attributes.fields.legacy_bios_bootable || 106 return p->attributes.fields.legacy_bios_bootable ||
107 !memcmp(&(p->partition_type_guid), &system_guid, 107 !memcmp(&(p->partition_type_guid), &system_guid,
108 sizeof(efi_guid_t)); 108 sizeof(efi_guid_t));
109 } 109 }
110 110
111 #ifdef CONFIG_EFI_PARTITION 111 #ifdef CONFIG_EFI_PARTITION
112 /* 112 /*
113 * Public Functions (include/part.h) 113 * Public Functions (include/part.h)
114 */ 114 */
115 115
116 void print_part_efi(block_dev_desc_t * dev_desc) 116 void print_part_efi(block_dev_desc_t * dev_desc)
117 { 117 {
118 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz); 118 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
119 gpt_entry *gpt_pte = NULL; 119 gpt_entry *gpt_pte = NULL;
120 int i = 0; 120 int i = 0;
121 char uuid[37]; 121 char uuid[37];
122 122
123 if (!dev_desc) { 123 if (!dev_desc) {
124 printf("%s: Invalid Argument(s)\n", __func__); 124 printf("%s: Invalid Argument(s)\n", __func__);
125 return; 125 return;
126 } 126 }
127 /* This function validates AND fills in the GPT header and PTE */ 127 /* This function validates AND fills in the GPT header and PTE */
128 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, 128 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
129 gpt_head, &gpt_pte) != 1) { 129 gpt_head, &gpt_pte) != 1) {
130 printf("%s: *** ERROR: Invalid GPT ***\n", __func__); 130 printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
131 return; 131 return;
132 } 132 }
133 133
134 debug("%s: gpt-entry at %p\n", __func__, gpt_pte); 134 debug("%s: gpt-entry at %p\n", __func__, gpt_pte);
135 135
136 printf("Part\tStart LBA\tEnd LBA\t\tName\n"); 136 printf("Part\tStart LBA\tEnd LBA\t\tName\n");
137 printf("\tAttributes\n"); 137 printf("\tAttributes\n");
138 printf("\tType UUID\n"); 138 printf("\tType UUID\n");
139 printf("\tPartition UUID\n"); 139 printf("\tPartition UUID\n");
140 140
141 for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) { 141 for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) {
142 /* Stop at the first non valid PTE */ 142 /* Stop at the first non valid PTE */
143 if (!is_pte_valid(&gpt_pte[i])) 143 if (!is_pte_valid(&gpt_pte[i]))
144 break; 144 break;
145 145
146 printf("%3d\t0x%08llx\t0x%08llx\t\"%s\"\n", (i + 1), 146 printf("%3d\t0x%08llx\t0x%08llx\t\"%s\"\n", (i + 1),
147 le64_to_cpu(gpt_pte[i].starting_lba), 147 le64_to_cpu(gpt_pte[i].starting_lba),
148 le64_to_cpu(gpt_pte[i].ending_lba), 148 le64_to_cpu(gpt_pte[i].ending_lba),
149 print_efiname(&gpt_pte[i])); 149 print_efiname(&gpt_pte[i]));
150 printf("\tattrs:\t0x%016llx\n", gpt_pte[i].attributes.raw); 150 printf("\tattrs:\t0x%016llx\n", gpt_pte[i].attributes.raw);
151 uuid_string(gpt_pte[i].partition_type_guid.b, uuid); 151 uuid_string(gpt_pte[i].partition_type_guid.b, uuid);
152 printf("\ttype:\t%s\n", uuid); 152 printf("\ttype:\t%s\n", uuid);
153 uuid_string(gpt_pte[i].unique_partition_guid.b, uuid); 153 uuid_string(gpt_pte[i].unique_partition_guid.b, uuid);
154 printf("\tuuid:\t%s\n", uuid); 154 printf("\tuuid:\t%s\n", uuid);
155 } 155 }
156 156
157 /* Remember to free pte */ 157 /* Remember to free pte */
158 free(gpt_pte); 158 free(gpt_pte);
159 return; 159 return;
160 } 160 }
161 161
162 int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, 162 int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
163 disk_partition_t * info) 163 disk_partition_t * info)
164 { 164 {
165 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz); 165 ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
166 gpt_entry *gpt_pte = NULL; 166 gpt_entry *gpt_pte = NULL;
167 167
168 /* "part" argument must be at least 1 */ 168 /* "part" argument must be at least 1 */
169 if (!dev_desc || !info || part < 1) { 169 if (!dev_desc || !info || part < 1) {
170 printf("%s: Invalid Argument(s)\n", __func__); 170 printf("%s: Invalid Argument(s)\n", __func__);
171 return -1; 171 return -1;
172 } 172 }
173 173
174 /* This function validates AND fills in the GPT header and PTE */ 174 /* This function validates AND fills in the GPT header and PTE */
175 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, 175 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
176 gpt_head, &gpt_pte) != 1) { 176 gpt_head, &gpt_pte) != 1) {
177 printf("%s: *** ERROR: Invalid GPT ***\n", __func__); 177 printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
178 return -1; 178 return -1;
179 } 179 }
180 180
181 if (part > le32_to_cpu(gpt_head->num_partition_entries) || 181 if (part > le32_to_cpu(gpt_head->num_partition_entries) ||
182 !is_pte_valid(&gpt_pte[part - 1])) { 182 !is_pte_valid(&gpt_pte[part - 1])) {
183 printf("%s: *** ERROR: Invalid partition number %d ***\n", 183 printf("%s: *** ERROR: Invalid partition number %d ***\n",
184 __func__, part); 184 __func__, part);
185 return -1; 185 return -1;
186 } 186 }
187 187
188 /* The ulong casting limits the maximum disk size to 2 TB */ 188 /* The ulong casting limits the maximum disk size to 2 TB */
189 info->start = (u64)le64_to_cpu(gpt_pte[part - 1].starting_lba); 189 info->start = (u64)le64_to_cpu(gpt_pte[part - 1].starting_lba);
190 /* The ending LBA is inclusive, to calculate size, add 1 to it */ 190 /* The ending LBA is inclusive, to calculate size, add 1 to it */
191 info->size = ((u64)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1) 191 info->size = ((u64)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1)
192 - info->start; 192 - info->start;
193 info->blksz = dev_desc->blksz; 193 info->blksz = dev_desc->blksz;
194 194
195 sprintf((char *)info->name, "%s", 195 sprintf((char *)info->name, "%s",
196 print_efiname(&gpt_pte[part - 1])); 196 print_efiname(&gpt_pte[part - 1]));
197 sprintf((char *)info->type, "U-Boot"); 197 sprintf((char *)info->type, "U-Boot");
198 info->bootable = is_bootable(&gpt_pte[part - 1]); 198 info->bootable = is_bootable(&gpt_pte[part - 1]);
199 #ifdef CONFIG_PARTITION_UUIDS 199 #ifdef CONFIG_PARTITION_UUIDS
200 uuid_string(gpt_pte[part - 1].unique_partition_guid.b, info->uuid); 200 uuid_string(gpt_pte[part - 1].unique_partition_guid.b, info->uuid);
201 #endif 201 #endif
202 202
203 debug("%s: start 0x%lX, size 0x%lX, name %s", __func__, 203 debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s", __func__,
204 info->start, info->size, info->name); 204 info->start, info->size, info->name);
205 205
206 /* Remember to free pte */ 206 /* Remember to free pte */
207 free(gpt_pte); 207 free(gpt_pte);
208 return 0; 208 return 0;
209 } 209 }
210 210
211 int test_part_efi(block_dev_desc_t * dev_desc) 211 int test_part_efi(block_dev_desc_t * dev_desc)
212 { 212 {
213 ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc->blksz); 213 ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc->blksz);
214 214
215 /* Read legacy MBR from block 0 and validate it */ 215 /* Read legacy MBR from block 0 and validate it */
216 if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)legacymbr) != 1) 216 if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)legacymbr) != 1)
217 || (is_pmbr_valid(legacymbr) != 1)) { 217 || (is_pmbr_valid(legacymbr) != 1)) {
218 return -1; 218 return -1;
219 } 219 }
220 return 0; 220 return 0;
221 } 221 }
222 222
223 /** 223 /**
224 * set_protective_mbr(): Set the EFI protective MBR 224 * set_protective_mbr(): Set the EFI protective MBR
225 * @param dev_desc - block device descriptor 225 * @param dev_desc - block device descriptor
226 * 226 *
227 * @return - zero on success, otherwise error 227 * @return - zero on success, otherwise error
228 */ 228 */
229 static int set_protective_mbr(block_dev_desc_t *dev_desc) 229 static int set_protective_mbr(block_dev_desc_t *dev_desc)
230 { 230 {
231 legacy_mbr *p_mbr; 231 legacy_mbr *p_mbr;
232 232
233 /* Setup the Protective MBR */ 233 /* Setup the Protective MBR */
234 p_mbr = calloc(1, sizeof(p_mbr)); 234 p_mbr = calloc(1, sizeof(p_mbr));
235 if (p_mbr == NULL) { 235 if (p_mbr == NULL) {
236 printf("%s: calloc failed!\n", __func__); 236 printf("%s: calloc failed!\n", __func__);
237 return -1; 237 return -1;
238 } 238 }
239 /* Append signature */ 239 /* Append signature */
240 p_mbr->signature = MSDOS_MBR_SIGNATURE; 240 p_mbr->signature = MSDOS_MBR_SIGNATURE;
241 p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT; 241 p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
242 p_mbr->partition_record[0].start_sect = 1; 242 p_mbr->partition_record[0].start_sect = 1;
243 p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba; 243 p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba;
244 244
245 /* Write MBR sector to the MMC device */ 245 /* Write MBR sector to the MMC device */
246 if (dev_desc->block_write(dev_desc->dev, 0, 1, p_mbr) != 1) { 246 if (dev_desc->block_write(dev_desc->dev, 0, 1, p_mbr) != 1) {
247 printf("** Can't write to device %d **\n", 247 printf("** Can't write to device %d **\n",
248 dev_desc->dev); 248 dev_desc->dev);
249 free(p_mbr); 249 free(p_mbr);
250 return -1; 250 return -1;
251 } 251 }
252 252
253 free(p_mbr); 253 free(p_mbr);
254 return 0; 254 return 0;
255 } 255 }
256 256
257 /** 257 /**
258 * string_uuid(); Convert UUID stored as string to bytes 258 * string_uuid(); Convert UUID stored as string to bytes
259 * 259 *
260 * @param uuid - UUID represented as string 260 * @param uuid - UUID represented as string
261 * @param dst - GUID buffer 261 * @param dst - GUID buffer
262 * 262 *
263 * @return return 0 on successful conversion 263 * @return return 0 on successful conversion
264 */ 264 */
265 static int string_uuid(char *uuid, u8 *dst) 265 static int string_uuid(char *uuid, u8 *dst)
266 { 266 {
267 efi_guid_t guid; 267 efi_guid_t guid;
268 u16 b, c, d; 268 u16 b, c, d;
269 u64 e; 269 u64 e;
270 u32 a; 270 u32 a;
271 u8 *p; 271 u8 *p;
272 u8 i; 272 u8 i;
273 273
274 const u8 uuid_str_len = 36; 274 const u8 uuid_str_len = 36;
275 275
276 /* The UUID is written in text: */ 276 /* The UUID is written in text: */
277 /* 1 9 14 19 24 */ 277 /* 1 9 14 19 24 */
278 /* xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx */ 278 /* xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx */
279 279
280 debug("%s: uuid: %s\n", __func__, uuid); 280 debug("%s: uuid: %s\n", __func__, uuid);
281 281
282 if (strlen(uuid) != uuid_str_len) 282 if (strlen(uuid) != uuid_str_len)
283 return -1; 283 return -1;
284 284
285 for (i = 0; i < uuid_str_len; i++) { 285 for (i = 0; i < uuid_str_len; i++) {
286 if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) { 286 if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) {
287 if (uuid[i] != '-') 287 if (uuid[i] != '-')
288 return -1; 288 return -1;
289 } else { 289 } else {
290 if (!isxdigit(uuid[i])) 290 if (!isxdigit(uuid[i]))
291 return -1; 291 return -1;
292 } 292 }
293 } 293 }
294 294
295 a = (u32)simple_strtoul(uuid, NULL, 16); 295 a = (u32)simple_strtoul(uuid, NULL, 16);
296 b = (u16)simple_strtoul(uuid + 9, NULL, 16); 296 b = (u16)simple_strtoul(uuid + 9, NULL, 16);
297 c = (u16)simple_strtoul(uuid + 14, NULL, 16); 297 c = (u16)simple_strtoul(uuid + 14, NULL, 16);
298 d = (u16)simple_strtoul(uuid + 19, NULL, 16); 298 d = (u16)simple_strtoul(uuid + 19, NULL, 16);
299 e = (u64)simple_strtoull(uuid + 24, NULL, 16); 299 e = (u64)simple_strtoull(uuid + 24, NULL, 16);
300 300
301 p = (u8 *) &e; 301 p = (u8 *) &e;
302 guid = EFI_GUID(a, b, c, d >> 8, d & 0xFF, 302 guid = EFI_GUID(a, b, c, d >> 8, d & 0xFF,
303 *(p + 5), *(p + 4), *(p + 3), 303 *(p + 5), *(p + 4), *(p + 3),
304 *(p + 2), *(p + 1) , *p); 304 *(p + 2), *(p + 1) , *p);
305 305
306 memcpy(dst, guid.b, sizeof(efi_guid_t)); 306 memcpy(dst, guid.b, sizeof(efi_guid_t));
307 307
308 return 0; 308 return 0;
309 } 309 }
310 310
311 int write_gpt_table(block_dev_desc_t *dev_desc, 311 int write_gpt_table(block_dev_desc_t *dev_desc,
312 gpt_header *gpt_h, gpt_entry *gpt_e) 312 gpt_header *gpt_h, gpt_entry *gpt_e)
313 { 313 {
314 const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries 314 const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries
315 * sizeof(gpt_entry)), dev_desc); 315 * sizeof(gpt_entry)), dev_desc);
316 u32 calc_crc32; 316 u32 calc_crc32;
317 u64 val; 317 u64 val;
318 318
319 debug("max lba: %x\n", (u32) dev_desc->lba); 319 debug("max lba: %x\n", (u32) dev_desc->lba);
320 /* Setup the Protective MBR */ 320 /* Setup the Protective MBR */
321 if (set_protective_mbr(dev_desc) < 0) 321 if (set_protective_mbr(dev_desc) < 0)
322 goto err; 322 goto err;
323 323
324 /* Generate CRC for the Primary GPT Header */ 324 /* Generate CRC for the Primary GPT Header */
325 calc_crc32 = efi_crc32((const unsigned char *)gpt_e, 325 calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
326 le32_to_cpu(gpt_h->num_partition_entries) * 326 le32_to_cpu(gpt_h->num_partition_entries) *
327 le32_to_cpu(gpt_h->sizeof_partition_entry)); 327 le32_to_cpu(gpt_h->sizeof_partition_entry));
328 gpt_h->partition_entry_array_crc32 = cpu_to_le32(calc_crc32); 328 gpt_h->partition_entry_array_crc32 = cpu_to_le32(calc_crc32);
329 329
330 calc_crc32 = efi_crc32((const unsigned char *)gpt_h, 330 calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
331 le32_to_cpu(gpt_h->header_size)); 331 le32_to_cpu(gpt_h->header_size));
332 gpt_h->header_crc32 = cpu_to_le32(calc_crc32); 332 gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
333 333
334 /* Write the First GPT to the block right after the Legacy MBR */ 334 /* Write the First GPT to the block right after the Legacy MBR */
335 if (dev_desc->block_write(dev_desc->dev, 1, 1, gpt_h) != 1) 335 if (dev_desc->block_write(dev_desc->dev, 1, 1, gpt_h) != 1)
336 goto err; 336 goto err;
337 337
338 if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_cnt, gpt_e) 338 if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_cnt, gpt_e)
339 != pte_blk_cnt) 339 != pte_blk_cnt)
340 goto err; 340 goto err;
341 341
342 /* recalculate the values for the Second GPT Header */ 342 /* recalculate the values for the Second GPT Header */
343 val = le64_to_cpu(gpt_h->my_lba); 343 val = le64_to_cpu(gpt_h->my_lba);
344 gpt_h->my_lba = gpt_h->alternate_lba; 344 gpt_h->my_lba = gpt_h->alternate_lba;
345 gpt_h->alternate_lba = cpu_to_le64(val); 345 gpt_h->alternate_lba = cpu_to_le64(val);
346 gpt_h->header_crc32 = 0; 346 gpt_h->header_crc32 = 0;
347 347
348 calc_crc32 = efi_crc32((const unsigned char *)gpt_h, 348 calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
349 le32_to_cpu(gpt_h->header_size)); 349 le32_to_cpu(gpt_h->header_size));
350 gpt_h->header_crc32 = cpu_to_le32(calc_crc32); 350 gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
351 351
352 if (dev_desc->block_write(dev_desc->dev, 352 if (dev_desc->block_write(dev_desc->dev,
353 le32_to_cpu(gpt_h->last_usable_lba + 1), 353 le32_to_cpu(gpt_h->last_usable_lba + 1),
354 pte_blk_cnt, gpt_e) != pte_blk_cnt) 354 pte_blk_cnt, gpt_e) != pte_blk_cnt)
355 goto err; 355 goto err;
356 356
357 if (dev_desc->block_write(dev_desc->dev, 357 if (dev_desc->block_write(dev_desc->dev,
358 le32_to_cpu(gpt_h->my_lba), 1, gpt_h) != 1) 358 le32_to_cpu(gpt_h->my_lba), 1, gpt_h) != 1)
359 goto err; 359 goto err;
360 360
361 debug("GPT successfully written to block device!\n"); 361 debug("GPT successfully written to block device!\n");
362 return 0; 362 return 0;
363 363
364 err: 364 err:
365 printf("** Can't write to device %d **\n", dev_desc->dev); 365 printf("** Can't write to device %d **\n", dev_desc->dev);
366 return -1; 366 return -1;
367 } 367 }
368 368
369 int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, 369 int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
370 disk_partition_t *partitions, int parts) 370 disk_partition_t *partitions, int parts)
371 { 371 {
372 u32 offset = (u32)le32_to_cpu(gpt_h->first_usable_lba); 372 u32 offset = (u32)le32_to_cpu(gpt_h->first_usable_lba);
373 ulong start; 373 ulong start;
374 int i, k; 374 int i, k;
375 size_t efiname_len, dosname_len; 375 size_t efiname_len, dosname_len;
376 #ifdef CONFIG_PARTITION_UUIDS 376 #ifdef CONFIG_PARTITION_UUIDS
377 char *str_uuid; 377 char *str_uuid;
378 #endif 378 #endif
379 379
380 for (i = 0; i < parts; i++) { 380 for (i = 0; i < parts; i++) {
381 /* partition starting lba */ 381 /* partition starting lba */
382 start = partitions[i].start; 382 start = partitions[i].start;
383 if (start && (start < offset)) { 383 if (start && (start < offset)) {
384 printf("Partition overlap\n"); 384 printf("Partition overlap\n");
385 return -1; 385 return -1;
386 } 386 }
387 if (start) { 387 if (start) {
388 gpt_e[i].starting_lba = cpu_to_le64(start); 388 gpt_e[i].starting_lba = cpu_to_le64(start);
389 offset = start + partitions[i].size; 389 offset = start + partitions[i].size;
390 } else { 390 } else {
391 gpt_e[i].starting_lba = cpu_to_le64(offset); 391 gpt_e[i].starting_lba = cpu_to_le64(offset);
392 offset += partitions[i].size; 392 offset += partitions[i].size;
393 } 393 }
394 if (offset >= gpt_h->last_usable_lba) { 394 if (offset >= gpt_h->last_usable_lba) {
395 printf("Partitions layout exceds disk size\n"); 395 printf("Partitions layout exceds disk size\n");
396 return -1; 396 return -1;
397 } 397 }
398 /* partition ending lba */ 398 /* partition ending lba */
399 if ((i == parts - 1) && (partitions[i].size == 0)) 399 if ((i == parts - 1) && (partitions[i].size == 0))
400 /* extend the last partition to maximuim */ 400 /* extend the last partition to maximuim */
401 gpt_e[i].ending_lba = gpt_h->last_usable_lba; 401 gpt_e[i].ending_lba = gpt_h->last_usable_lba;
402 else 402 else
403 gpt_e[i].ending_lba = cpu_to_le64(offset - 1); 403 gpt_e[i].ending_lba = cpu_to_le64(offset - 1);
404 404
405 /* partition type GUID */ 405 /* partition type GUID */
406 memcpy(gpt_e[i].partition_type_guid.b, 406 memcpy(gpt_e[i].partition_type_guid.b,
407 &PARTITION_BASIC_DATA_GUID, 16); 407 &PARTITION_BASIC_DATA_GUID, 16);
408 408
409 #ifdef CONFIG_PARTITION_UUIDS 409 #ifdef CONFIG_PARTITION_UUIDS
410 str_uuid = partitions[i].uuid; 410 str_uuid = partitions[i].uuid;
411 if (string_uuid(str_uuid, gpt_e[i].unique_partition_guid.b)) { 411 if (string_uuid(str_uuid, gpt_e[i].unique_partition_guid.b)) {
412 printf("Partition no. %d: invalid guid: %s\n", 412 printf("Partition no. %d: invalid guid: %s\n",
413 i, str_uuid); 413 i, str_uuid);
414 return -1; 414 return -1;
415 } 415 }
416 #endif 416 #endif
417 417
418 /* partition attributes */ 418 /* partition attributes */
419 memset(&gpt_e[i].attributes, 0, 419 memset(&gpt_e[i].attributes, 0,
420 sizeof(gpt_entry_attributes)); 420 sizeof(gpt_entry_attributes));
421 421
422 /* partition name */ 422 /* partition name */
423 efiname_len = sizeof(gpt_e[i].partition_name) 423 efiname_len = sizeof(gpt_e[i].partition_name)
424 / sizeof(efi_char16_t); 424 / sizeof(efi_char16_t);
425 dosname_len = sizeof(partitions[i].name); 425 dosname_len = sizeof(partitions[i].name);
426 426
427 memset(gpt_e[i].partition_name, 0, 427 memset(gpt_e[i].partition_name, 0,
428 sizeof(gpt_e[i].partition_name)); 428 sizeof(gpt_e[i].partition_name));
429 429
430 for (k = 0; k < min(dosname_len, efiname_len); k++) 430 for (k = 0; k < min(dosname_len, efiname_len); k++)
431 gpt_e[i].partition_name[k] = 431 gpt_e[i].partition_name[k] =
432 (efi_char16_t)(partitions[i].name[k]); 432 (efi_char16_t)(partitions[i].name[k]);
433 433
434 debug("%s: name: %s offset[%d]: 0x%x size[%d]: 0x%lx\n", 434 debug("%s: name: %s offset[%d]: 0x%x size[%d]: 0x" LBAF "\n",
435 __func__, partitions[i].name, i, 435 __func__, partitions[i].name, i,
436 offset, i, partitions[i].size); 436 offset, i, partitions[i].size);
437 } 437 }
438 438
439 return 0; 439 return 0;
440 } 440 }
441 441
442 int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h, 442 int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h,
443 char *str_guid, int parts_count) 443 char *str_guid, int parts_count)
444 { 444 {
445 gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE); 445 gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
446 gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1); 446 gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
447 gpt_h->header_size = cpu_to_le32(sizeof(gpt_header)); 447 gpt_h->header_size = cpu_to_le32(sizeof(gpt_header));
448 gpt_h->my_lba = cpu_to_le64(1); 448 gpt_h->my_lba = cpu_to_le64(1);
449 gpt_h->alternate_lba = cpu_to_le64(dev_desc->lba - 1); 449 gpt_h->alternate_lba = cpu_to_le64(dev_desc->lba - 1);
450 gpt_h->first_usable_lba = cpu_to_le64(34); 450 gpt_h->first_usable_lba = cpu_to_le64(34);
451 gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34); 451 gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34);
452 gpt_h->partition_entry_lba = cpu_to_le64(2); 452 gpt_h->partition_entry_lba = cpu_to_le64(2);
453 gpt_h->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS); 453 gpt_h->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
454 gpt_h->sizeof_partition_entry = cpu_to_le32(sizeof(gpt_entry)); 454 gpt_h->sizeof_partition_entry = cpu_to_le32(sizeof(gpt_entry));
455 gpt_h->header_crc32 = 0; 455 gpt_h->header_crc32 = 0;
456 gpt_h->partition_entry_array_crc32 = 0; 456 gpt_h->partition_entry_array_crc32 = 0;
457 457
458 if (string_uuid(str_guid, gpt_h->disk_guid.b)) 458 if (string_uuid(str_guid, gpt_h->disk_guid.b))
459 return -1; 459 return -1;
460 460
461 return 0; 461 return 0;
462 } 462 }
463 463
464 int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid, 464 int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
465 disk_partition_t *partitions, int parts_count) 465 disk_partition_t *partitions, int parts_count)
466 { 466 {
467 int ret; 467 int ret;
468 468
469 gpt_header *gpt_h = calloc(1, PAD_TO_BLOCKSIZE(sizeof(gpt_header), 469 gpt_header *gpt_h = calloc(1, PAD_TO_BLOCKSIZE(sizeof(gpt_header),
470 dev_desc)); 470 dev_desc));
471 gpt_entry *gpt_e; 471 gpt_entry *gpt_e;
472 472
473 if (gpt_h == NULL) { 473 if (gpt_h == NULL) {
474 printf("%s: calloc failed!\n", __func__); 474 printf("%s: calloc failed!\n", __func__);
475 return -1; 475 return -1;
476 } 476 }
477 477
478 gpt_e = calloc(1, PAD_TO_BLOCKSIZE(GPT_ENTRY_NUMBERS 478 gpt_e = calloc(1, PAD_TO_BLOCKSIZE(GPT_ENTRY_NUMBERS
479 * sizeof(gpt_entry), 479 * sizeof(gpt_entry),
480 dev_desc)); 480 dev_desc));
481 if (gpt_e == NULL) { 481 if (gpt_e == NULL) {
482 printf("%s: calloc failed!\n", __func__); 482 printf("%s: calloc failed!\n", __func__);
483 free(gpt_h); 483 free(gpt_h);
484 return -1; 484 return -1;
485 } 485 }
486 486
487 /* Generate Primary GPT header (LBA1) */ 487 /* Generate Primary GPT header (LBA1) */
488 ret = gpt_fill_header(dev_desc, gpt_h, str_disk_guid, parts_count); 488 ret = gpt_fill_header(dev_desc, gpt_h, str_disk_guid, parts_count);
489 if (ret) 489 if (ret)
490 goto err; 490 goto err;
491 491
492 /* Generate partition entries */ 492 /* Generate partition entries */
493 ret = gpt_fill_pte(gpt_h, gpt_e, partitions, parts_count); 493 ret = gpt_fill_pte(gpt_h, gpt_e, partitions, parts_count);
494 if (ret) 494 if (ret)
495 goto err; 495 goto err;
496 496
497 /* Write GPT partition table */ 497 /* Write GPT partition table */
498 ret = write_gpt_table(dev_desc, gpt_h, gpt_e); 498 ret = write_gpt_table(dev_desc, gpt_h, gpt_e);
499 499
500 err: 500 err:
501 free(gpt_e); 501 free(gpt_e);
502 free(gpt_h); 502 free(gpt_h);
503 return ret; 503 return ret;
504 } 504 }
505 #endif 505 #endif
506 506
507 /* 507 /*
508 * Private functions 508 * Private functions
509 */ 509 */
510 /* 510 /*
511 * pmbr_part_valid(): Check for EFI partition signature 511 * pmbr_part_valid(): Check for EFI partition signature
512 * 512 *
513 * Returns: 1 if EFI GPT partition type is found. 513 * Returns: 1 if EFI GPT partition type is found.
514 */ 514 */
515 static int pmbr_part_valid(struct partition *part) 515 static int pmbr_part_valid(struct partition *part)
516 { 516 {
517 if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT && 517 if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
518 get_unaligned_le32(&part->start_sect) == 1UL) { 518 get_unaligned_le32(&part->start_sect) == 1UL) {
519 return 1; 519 return 1;
520 } 520 }
521 521
522 return 0; 522 return 0;
523 } 523 }
524 524
525 /* 525 /*
526 * is_pmbr_valid(): test Protective MBR for validity 526 * is_pmbr_valid(): test Protective MBR for validity
527 * 527 *
528 * Returns: 1 if PMBR is valid, 0 otherwise. 528 * Returns: 1 if PMBR is valid, 0 otherwise.
529 * Validity depends on two things: 529 * Validity depends on two things:
530 * 1) MSDOS signature is in the last two bytes of the MBR 530 * 1) MSDOS signature is in the last two bytes of the MBR
531 * 2) One partition of type 0xEE is found, checked by pmbr_part_valid() 531 * 2) One partition of type 0xEE is found, checked by pmbr_part_valid()
532 */ 532 */
533 static int is_pmbr_valid(legacy_mbr * mbr) 533 static int is_pmbr_valid(legacy_mbr * mbr)
534 { 534 {
535 int i = 0; 535 int i = 0;
536 536
537 if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) 537 if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
538 return 0; 538 return 0;
539 539
540 for (i = 0; i < 4; i++) { 540 for (i = 0; i < 4; i++) {
541 if (pmbr_part_valid(&mbr->partition_record[i])) { 541 if (pmbr_part_valid(&mbr->partition_record[i])) {
542 return 1; 542 return 1;
543 } 543 }
544 } 544 }
545 return 0; 545 return 0;
546 } 546 }
547 547
548 /** 548 /**
549 * is_gpt_valid() - tests one GPT header and PTEs for validity 549 * is_gpt_valid() - tests one GPT header and PTEs for validity
550 * 550 *
551 * lba is the logical block address of the GPT header to test 551 * lba is the logical block address of the GPT header to test
552 * gpt is a GPT header ptr, filled on return. 552 * gpt is a GPT header ptr, filled on return.
553 * ptes is a PTEs ptr, filled on return. 553 * ptes is a PTEs ptr, filled on return.
554 * 554 *
555 * Description: returns 1 if valid, 0 on error. 555 * Description: returns 1 if valid, 0 on error.
556 * If valid, returns pointers to PTEs. 556 * If valid, returns pointers to PTEs.
557 */ 557 */
558 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, 558 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
559 gpt_header * pgpt_head, gpt_entry ** pgpt_pte) 559 gpt_header * pgpt_head, gpt_entry ** pgpt_pte)
560 { 560 {
561 u32 crc32_backup = 0; 561 u32 crc32_backup = 0;
562 u32 calc_crc32; 562 u32 calc_crc32;
563 unsigned long long lastlba; 563 unsigned long long lastlba;
564 564
565 if (!dev_desc || !pgpt_head) { 565 if (!dev_desc || !pgpt_head) {
566 printf("%s: Invalid Argument(s)\n", __func__); 566 printf("%s: Invalid Argument(s)\n", __func__);
567 return 0; 567 return 0;
568 } 568 }
569 569
570 /* Read GPT Header from device */ 570 /* Read GPT Header from device */
571 if (dev_desc->block_read(dev_desc->dev, lba, 1, pgpt_head) != 1) { 571 if (dev_desc->block_read(dev_desc->dev, lba, 1, pgpt_head) != 1) {
572 printf("*** ERROR: Can't read GPT header ***\n"); 572 printf("*** ERROR: Can't read GPT header ***\n");
573 return 0; 573 return 0;
574 } 574 }
575 575
576 /* Check the GPT header signature */ 576 /* Check the GPT header signature */
577 if (le64_to_cpu(pgpt_head->signature) != GPT_HEADER_SIGNATURE) { 577 if (le64_to_cpu(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
578 printf("GUID Partition Table Header signature is wrong:" 578 printf("GUID Partition Table Header signature is wrong:"
579 "0x%llX != 0x%llX\n", 579 "0x%llX != 0x%llX\n",
580 le64_to_cpu(pgpt_head->signature), 580 le64_to_cpu(pgpt_head->signature),
581 GPT_HEADER_SIGNATURE); 581 GPT_HEADER_SIGNATURE);
582 return 0; 582 return 0;
583 } 583 }
584 584
585 /* Check the GUID Partition Table CRC */ 585 /* Check the GUID Partition Table CRC */
586 memcpy(&crc32_backup, &pgpt_head->header_crc32, sizeof(crc32_backup)); 586 memcpy(&crc32_backup, &pgpt_head->header_crc32, sizeof(crc32_backup));
587 memset(&pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32)); 587 memset(&pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
588 588
589 calc_crc32 = efi_crc32((const unsigned char *)pgpt_head, 589 calc_crc32 = efi_crc32((const unsigned char *)pgpt_head,
590 le32_to_cpu(pgpt_head->header_size)); 590 le32_to_cpu(pgpt_head->header_size));
591 591
592 memcpy(&pgpt_head->header_crc32, &crc32_backup, sizeof(crc32_backup)); 592 memcpy(&pgpt_head->header_crc32, &crc32_backup, sizeof(crc32_backup));
593 593
594 if (calc_crc32 != le32_to_cpu(crc32_backup)) { 594 if (calc_crc32 != le32_to_cpu(crc32_backup)) {
595 printf("GUID Partition Table Header CRC is wrong:" 595 printf("GUID Partition Table Header CRC is wrong:"
596 "0x%x != 0x%x\n", 596 "0x%x != 0x%x\n",
597 le32_to_cpu(crc32_backup), calc_crc32); 597 le32_to_cpu(crc32_backup), calc_crc32);
598 return 0; 598 return 0;
599 } 599 }
600 600
601 /* Check that the my_lba entry points to the LBA that contains the GPT */ 601 /* Check that the my_lba entry points to the LBA that contains the GPT */
602 if (le64_to_cpu(pgpt_head->my_lba) != lba) { 602 if (le64_to_cpu(pgpt_head->my_lba) != lba) {
603 printf("GPT: my_lba incorrect: %llX != %llX\n", 603 printf("GPT: my_lba incorrect: %llX != %llX\n",
604 le64_to_cpu(pgpt_head->my_lba), 604 le64_to_cpu(pgpt_head->my_lba),
605 lba); 605 lba);
606 return 0; 606 return 0;
607 } 607 }
608 608
609 /* Check the first_usable_lba and last_usable_lba are within the disk. */ 609 /* Check the first_usable_lba and last_usable_lba are within the disk. */
610 lastlba = (unsigned long long)dev_desc->lba; 610 lastlba = (unsigned long long)dev_desc->lba;
611 if (le64_to_cpu(pgpt_head->first_usable_lba) > lastlba) { 611 if (le64_to_cpu(pgpt_head->first_usable_lba) > lastlba) {
612 printf("GPT: first_usable_lba incorrect: %llX > %llX\n", 612 printf("GPT: first_usable_lba incorrect: %llX > %llX\n",
613 le64_to_cpu(pgpt_head->first_usable_lba), lastlba); 613 le64_to_cpu(pgpt_head->first_usable_lba), lastlba);
614 return 0; 614 return 0;
615 } 615 }
616 if (le64_to_cpu(pgpt_head->last_usable_lba) > lastlba) { 616 if (le64_to_cpu(pgpt_head->last_usable_lba) > lastlba) {
617 printf("GPT: last_usable_lba incorrect: %llX > %llX\n", 617 printf("GPT: last_usable_lba incorrect: %llX > %llX\n",
618 (u64) le64_to_cpu(pgpt_head->last_usable_lba), lastlba); 618 (u64) le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
619 return 0; 619 return 0;
620 } 620 }
621 621
622 debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n", 622 debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n",
623 le64_to_cpu(pgpt_head->first_usable_lba), 623 le64_to_cpu(pgpt_head->first_usable_lba),
624 le64_to_cpu(pgpt_head->last_usable_lba), lastlba); 624 le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
625 625
626 /* Read and allocate Partition Table Entries */ 626 /* Read and allocate Partition Table Entries */
627 *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head); 627 *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
628 if (*pgpt_pte == NULL) { 628 if (*pgpt_pte == NULL) {
629 printf("GPT: Failed to allocate memory for PTE\n"); 629 printf("GPT: Failed to allocate memory for PTE\n");
630 return 0; 630 return 0;
631 } 631 }
632 632
633 /* Check the GUID Partition Table Entry Array CRC */ 633 /* Check the GUID Partition Table Entry Array CRC */
634 calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte, 634 calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte,
635 le32_to_cpu(pgpt_head->num_partition_entries) * 635 le32_to_cpu(pgpt_head->num_partition_entries) *
636 le32_to_cpu(pgpt_head->sizeof_partition_entry)); 636 le32_to_cpu(pgpt_head->sizeof_partition_entry));
637 637
638 if (calc_crc32 != le32_to_cpu(pgpt_head->partition_entry_array_crc32)) { 638 if (calc_crc32 != le32_to_cpu(pgpt_head->partition_entry_array_crc32)) {
639 printf("GUID Partition Table Entry Array CRC is wrong:" 639 printf("GUID Partition Table Entry Array CRC is wrong:"
640 "0x%x != 0x%x\n", 640 "0x%x != 0x%x\n",
641 le32_to_cpu(pgpt_head->partition_entry_array_crc32), 641 le32_to_cpu(pgpt_head->partition_entry_array_crc32),
642 calc_crc32); 642 calc_crc32);
643 643
644 free(*pgpt_pte); 644 free(*pgpt_pte);
645 return 0; 645 return 0;
646 } 646 }
647 647
648 /* We're done, all's well */ 648 /* We're done, all's well */
649 return 1; 649 return 1;
650 } 650 }
651 651
652 /** 652 /**
653 * alloc_read_gpt_entries(): reads partition entries from disk 653 * alloc_read_gpt_entries(): reads partition entries from disk
654 * @dev_desc 654 * @dev_desc
655 * @gpt - GPT header 655 * @gpt - GPT header
656 * 656 *
657 * Description: Returns ptes on success, NULL on error. 657 * Description: Returns ptes on success, NULL on error.
658 * Allocates space for PTEs based on information found in @gpt. 658 * Allocates space for PTEs based on information found in @gpt.
659 * Notes: remember to free pte when you're done! 659 * Notes: remember to free pte when you're done!
660 */ 660 */
661 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, 661 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
662 gpt_header * pgpt_head) 662 gpt_header * pgpt_head)
663 { 663 {
664 size_t count = 0, blk_cnt; 664 size_t count = 0, blk_cnt;
665 gpt_entry *pte = NULL; 665 gpt_entry *pte = NULL;
666 666
667 if (!dev_desc || !pgpt_head) { 667 if (!dev_desc || !pgpt_head) {
668 printf("%s: Invalid Argument(s)\n", __func__); 668 printf("%s: Invalid Argument(s)\n", __func__);
669 return NULL; 669 return NULL;
670 } 670 }
671 671
672 count = le32_to_cpu(pgpt_head->num_partition_entries) * 672 count = le32_to_cpu(pgpt_head->num_partition_entries) *
673 le32_to_cpu(pgpt_head->sizeof_partition_entry); 673 le32_to_cpu(pgpt_head->sizeof_partition_entry);
674 674
675 debug("%s: count = %u * %u = %zu\n", __func__, 675 debug("%s: count = %u * %u = %zu\n", __func__,
676 (u32) le32_to_cpu(pgpt_head->num_partition_entries), 676 (u32) le32_to_cpu(pgpt_head->num_partition_entries),
677 (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry), count); 677 (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry), count);
678 678
679 /* Allocate memory for PTE, remember to FREE */ 679 /* Allocate memory for PTE, remember to FREE */
680 if (count != 0) { 680 if (count != 0) {
681 pte = memalign(ARCH_DMA_MINALIGN, 681 pte = memalign(ARCH_DMA_MINALIGN,
682 PAD_TO_BLOCKSIZE(count, dev_desc)); 682 PAD_TO_BLOCKSIZE(count, dev_desc));
683 } 683 }
684 684
685 if (count == 0 || pte == NULL) { 685 if (count == 0 || pte == NULL) {
686 printf("%s: ERROR: Can't allocate 0x%zX " 686 printf("%s: ERROR: Can't allocate 0x%zX "
687 "bytes for GPT Entries\n", 687 "bytes for GPT Entries\n",
688 __func__, count); 688 __func__, count);
689 return NULL; 689 return NULL;
690 } 690 }
691 691
692 /* Read GPT Entries from device */ 692 /* Read GPT Entries from device */
693 blk_cnt = BLOCK_CNT(count, dev_desc); 693 blk_cnt = BLOCK_CNT(count, dev_desc);
694 if (dev_desc->block_read (dev_desc->dev, 694 if (dev_desc->block_read (dev_desc->dev,
695 le64_to_cpu(pgpt_head->partition_entry_lba), 695 le64_to_cpu(pgpt_head->partition_entry_lba),
696 (lbaint_t) (blk_cnt), pte) 696 (lbaint_t) (blk_cnt), pte)
697 != blk_cnt) { 697 != blk_cnt) {
698 698
699 printf("*** ERROR: Can't read GPT Entries ***\n"); 699 printf("*** ERROR: Can't read GPT Entries ***\n");
700 free(pte); 700 free(pte);
701 return NULL; 701 return NULL;
702 } 702 }
703 return pte; 703 return pte;
704 } 704 }
705 705
706 /** 706 /**
707 * is_pte_valid(): validates a single Partition Table Entry 707 * is_pte_valid(): validates a single Partition Table Entry
708 * @gpt_entry - Pointer to a single Partition Table Entry 708 * @gpt_entry - Pointer to a single Partition Table Entry
709 * 709 *
710 * Description: returns 1 if valid, 0 on error. 710 * Description: returns 1 if valid, 0 on error.
711 */ 711 */
712 static int is_pte_valid(gpt_entry * pte) 712 static int is_pte_valid(gpt_entry * pte)
713 { 713 {
714 efi_guid_t unused_guid; 714 efi_guid_t unused_guid;
715 715
716 if (!pte) { 716 if (!pte) {
717 printf("%s: Invalid Argument(s)\n", __func__); 717 printf("%s: Invalid Argument(s)\n", __func__);
718 return 0; 718 return 0;
719 } 719 }
720 720
721 /* Only one validation for now: 721 /* Only one validation for now:
722 * The GUID Partition Type != Unused Entry (ALL-ZERO) 722 * The GUID Partition Type != Unused Entry (ALL-ZERO)
723 */ 723 */
724 memset(unused_guid.b, 0, sizeof(unused_guid.b)); 724 memset(unused_guid.b, 0, sizeof(unused_guid.b));
725 725
726 if (memcmp(pte->partition_type_guid.b, unused_guid.b, 726 if (memcmp(pte->partition_type_guid.b, unused_guid.b,
727 sizeof(unused_guid.b)) == 0) { 727 sizeof(unused_guid.b)) == 0) {
728 728
729 debug("%s: Found an unused PTE GUID at 0x%08X\n", __func__, 729 debug("%s: Found an unused PTE GUID at 0x%08X\n", __func__,
730 (unsigned int)(uintptr_t)pte); 730 (unsigned int)(uintptr_t)pte);
731 731
732 return 0; 732 return 0;
733 } else { 733 } else {
734 return 1; 734 return 1;
735 } 735 }
736 } 736 }
737 #endif 737 #endif
738 738
1 /* 1 /*
2 * (C) Copyright 2001 2 * (C) Copyright 2001
3 * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch. 3 * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch.
4 * 4 *
5 * See file CREDITS for list of people who contributed to this 5 * See file CREDITS for list of people who contributed to this
6 * project. 6 * project.
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of 10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version. 11 * the License, or (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA 21 * MA 02111-1307 USA
22 */ 22 */
23 23
24 #include <common.h> 24 #include <common.h>
25 #include <command.h> 25 #include <command.h>
26 #include "part_iso.h" 26 #include "part_iso.h"
27 27
28 #ifdef HAVE_BLOCK_DEVICE 28 #ifdef HAVE_BLOCK_DEVICE
29 29
30 /* #define ISO_PART_DEBUG */ 30 /* #define ISO_PART_DEBUG */
31 31
32 #ifdef ISO_PART_DEBUG 32 #ifdef ISO_PART_DEBUG
33 #define PRINTF(fmt,args...) printf (fmt ,##args) 33 #define PRINTF(fmt,args...) printf (fmt ,##args)
34 #else 34 #else
35 #define PRINTF(fmt,args...) 35 #define PRINTF(fmt,args...)
36 #endif 36 #endif
37 37
38 /* enable this if CDs are written with the PowerPC Platform ID */ 38 /* enable this if CDs are written with the PowerPC Platform ID */
39 #undef CHECK_FOR_POWERPC_PLATTFORM 39 #undef CHECK_FOR_POWERPC_PLATTFORM
40 #define CD_SECTSIZE 2048 40 #define CD_SECTSIZE 2048
41 41
42 static unsigned char tmpbuf[CD_SECTSIZE]; 42 static unsigned char tmpbuf[CD_SECTSIZE];
43 43
44 /* Convert char[4] in little endian format to the host format integer 44 /* Convert char[4] in little endian format to the host format integer
45 */ 45 */
46 static inline unsigned long le32_to_int(unsigned char *le32) 46 static inline unsigned long le32_to_int(unsigned char *le32)
47 { 47 {
48 return ((le32[3] << 24) + 48 return ((le32[3] << 24) +
49 (le32[2] << 16) + 49 (le32[2] << 16) +
50 (le32[1] << 8) + 50 (le32[1] << 8) +
51 le32[0] 51 le32[0]
52 ); 52 );
53 } 53 }
54 /* Convert char[2] in little endian format to the host format integer 54 /* Convert char[2] in little endian format to the host format integer
55 */ 55 */
56 static inline unsigned short le16_to_int(unsigned char *le16) 56 static inline unsigned short le16_to_int(unsigned char *le16)
57 { 57 {
58 return ((le16[1] << 8) + 58 return ((le16[1] << 8) +
59 le16[0] 59 le16[0]
60 ); 60 );
61 } 61 }
62 62
63 63
64 /* only boot records will be listed as valid partitions */ 64 /* only boot records will be listed as valid partitions */
65 int get_partition_info_iso_verb(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info, int verb) 65 int get_partition_info_iso_verb(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info, int verb)
66 { 66 {
67 int i,offset,entry_num; 67 int i,offset,entry_num;
68 unsigned short *chksumbuf; 68 unsigned short *chksumbuf;
69 unsigned short chksum; 69 unsigned short chksum;
70 unsigned long newblkaddr,blkaddr,lastsect,bootaddr; 70 unsigned long newblkaddr,blkaddr,lastsect,bootaddr;
71 iso_boot_rec_t *pbr = (iso_boot_rec_t *)tmpbuf; /* boot record */ 71 iso_boot_rec_t *pbr = (iso_boot_rec_t *)tmpbuf; /* boot record */
72 iso_pri_rec_t *ppr = (iso_pri_rec_t *)tmpbuf; /* primary desc */ 72 iso_pri_rec_t *ppr = (iso_pri_rec_t *)tmpbuf; /* primary desc */
73 iso_val_entry_t *pve = (iso_val_entry_t *)tmpbuf; 73 iso_val_entry_t *pve = (iso_val_entry_t *)tmpbuf;
74 iso_init_def_entry_t *pide; 74 iso_init_def_entry_t *pide;
75 75
76 if (dev_desc->blksz != CD_SECTSIZE) 76 if (dev_desc->blksz != CD_SECTSIZE)
77 return -1; 77 return -1;
78 78
79 /* the first sector (sector 0x10) must be a primary volume desc */ 79 /* the first sector (sector 0x10) must be a primary volume desc */
80 blkaddr=PVD_OFFSET; 80 blkaddr=PVD_OFFSET;
81 if (dev_desc->block_read (dev_desc->dev, PVD_OFFSET, 1, (ulong *) tmpbuf) != 1) 81 if (dev_desc->block_read (dev_desc->dev, PVD_OFFSET, 1, (ulong *) tmpbuf) != 1)
82 return (-1); 82 return (-1);
83 if(ppr->desctype!=0x01) { 83 if(ppr->desctype!=0x01) {
84 if(verb) 84 if(verb)
85 printf ("** First descriptor is NOT a primary desc on %d:%d **\n", 85 printf ("** First descriptor is NOT a primary desc on %d:%d **\n",
86 dev_desc->dev, part_num); 86 dev_desc->dev, part_num);
87 return (-1); 87 return (-1);
88 } 88 }
89 if(strncmp((char *)ppr->stand_ident,"CD001",5)!=0) { 89 if(strncmp((char *)ppr->stand_ident,"CD001",5)!=0) {
90 if(verb) 90 if(verb)
91 printf ("** Wrong ISO Ident: %s on %d:%d **\n", 91 printf ("** Wrong ISO Ident: %s on %d:%d **\n",
92 ppr->stand_ident,dev_desc->dev, part_num); 92 ppr->stand_ident,dev_desc->dev, part_num);
93 return (-1); 93 return (-1);
94 } 94 }
95 lastsect= ((ppr->firstsek_LEpathtab1_LE & 0x000000ff)<<24) + 95 lastsect= ((ppr->firstsek_LEpathtab1_LE & 0x000000ff)<<24) +
96 ((ppr->firstsek_LEpathtab1_LE & 0x0000ff00)<< 8) + 96 ((ppr->firstsek_LEpathtab1_LE & 0x0000ff00)<< 8) +
97 ((ppr->firstsek_LEpathtab1_LE & 0x00ff0000)>> 8) + 97 ((ppr->firstsek_LEpathtab1_LE & 0x00ff0000)>> 8) +
98 ((ppr->firstsek_LEpathtab1_LE & 0xff000000)>>24) ; 98 ((ppr->firstsek_LEpathtab1_LE & 0xff000000)>>24) ;
99 info->blksz=ppr->secsize_BE; /* assuming same block size for all entries */ 99 info->blksz=ppr->secsize_BE; /* assuming same block size for all entries */
100 PRINTF(" Lastsect:%08lx\n",lastsect); 100 PRINTF(" Lastsect:%08lx\n",lastsect);
101 for(i=blkaddr;i<lastsect;i++) { 101 for(i=blkaddr;i<lastsect;i++) {
102 PRINTF("Reading block %d\n", i); 102 PRINTF("Reading block %d\n", i);
103 if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *) tmpbuf) != 1) 103 if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *) tmpbuf) != 1)
104 return (-1); 104 return (-1);
105 if(ppr->desctype==0x00) 105 if(ppr->desctype==0x00)
106 break; /* boot entry found */ 106 break; /* boot entry found */
107 if(ppr->desctype==0xff) { 107 if(ppr->desctype==0xff) {
108 if(verb) 108 if(verb)
109 printf ("** No valid boot catalog found on %d:%d **\n", 109 printf ("** No valid boot catalog found on %d:%d **\n",
110 dev_desc->dev, part_num); 110 dev_desc->dev, part_num);
111 return (-1); 111 return (-1);
112 } 112 }
113 } 113 }
114 /* boot entry found */ 114 /* boot entry found */
115 if(strncmp(pbr->ident_str,"EL TORITO SPECIFICATION",23)!=0) { 115 if(strncmp(pbr->ident_str,"EL TORITO SPECIFICATION",23)!=0) {
116 if(verb) 116 if(verb)
117 printf ("** Wrong El Torito ident: %s on %d:%d **\n", 117 printf ("** Wrong El Torito ident: %s on %d:%d **\n",
118 pbr->ident_str,dev_desc->dev, part_num); 118 pbr->ident_str,dev_desc->dev, part_num);
119 return (-1); 119 return (-1);
120 } 120 }
121 bootaddr=le32_to_int(pbr->pointer); 121 bootaddr=le32_to_int(pbr->pointer);
122 PRINTF(" Boot Entry at: %08lX\n",bootaddr); 122 PRINTF(" Boot Entry at: %08lX\n",bootaddr);
123 if (dev_desc->block_read (dev_desc->dev, bootaddr, 1, (ulong *) tmpbuf) != 1) { 123 if (dev_desc->block_read (dev_desc->dev, bootaddr, 1, (ulong *) tmpbuf) != 1) {
124 if(verb) 124 if(verb)
125 printf ("** Can't read Boot Entry at %lX on %d:%d **\n", 125 printf ("** Can't read Boot Entry at %lX on %d:%d **\n",
126 bootaddr,dev_desc->dev, part_num); 126 bootaddr,dev_desc->dev, part_num);
127 return (-1); 127 return (-1);
128 } 128 }
129 chksum=0; 129 chksum=0;
130 chksumbuf = (unsigned short *)tmpbuf; 130 chksumbuf = (unsigned short *)tmpbuf;
131 for(i=0;i<0x10;i++) 131 for(i=0;i<0x10;i++)
132 chksum+=((chksumbuf[i] &0xff)<<8)+((chksumbuf[i] &0xff00)>>8); 132 chksum+=((chksumbuf[i] &0xff)<<8)+((chksumbuf[i] &0xff00)>>8);
133 if(chksum!=0) { 133 if(chksum!=0) {
134 if(verb) 134 if(verb)
135 printf ("** Checksum Error in booting catalog validation entry on %d:%d **\n", 135 printf ("** Checksum Error in booting catalog validation entry on %d:%d **\n",
136 dev_desc->dev, part_num); 136 dev_desc->dev, part_num);
137 return (-1); 137 return (-1);
138 } 138 }
139 if((pve->key[0]!=0x55)||(pve->key[1]!=0xAA)) { 139 if((pve->key[0]!=0x55)||(pve->key[1]!=0xAA)) {
140 if(verb) 140 if(verb)
141 printf ("** Key 0x55 0xAA error on %d:%d **\n", 141 printf ("** Key 0x55 0xAA error on %d:%d **\n",
142 dev_desc->dev, part_num); 142 dev_desc->dev, part_num);
143 return(-1); 143 return(-1);
144 } 144 }
145 #ifdef CHECK_FOR_POWERPC_PLATTFORM 145 #ifdef CHECK_FOR_POWERPC_PLATTFORM
146 if(pve->platform!=0x01) { 146 if(pve->platform!=0x01) {
147 if(verb) 147 if(verb)
148 printf ("** No PowerPC platform CD on %d:%d **\n", 148 printf ("** No PowerPC platform CD on %d:%d **\n",
149 dev_desc->dev, part_num); 149 dev_desc->dev, part_num);
150 return(-1); 150 return(-1);
151 } 151 }
152 #endif 152 #endif
153 /* the validation entry seems to be ok, now search the "partition" */ 153 /* the validation entry seems to be ok, now search the "partition" */
154 entry_num=0; 154 entry_num=0;
155 offset=0x20; 155 offset=0x20;
156 sprintf ((char *)info->type, "U-Boot"); 156 sprintf ((char *)info->type, "U-Boot");
157 switch(dev_desc->if_type) { 157 switch(dev_desc->if_type) {
158 case IF_TYPE_IDE: 158 case IF_TYPE_IDE:
159 case IF_TYPE_SATA: 159 case IF_TYPE_SATA:
160 case IF_TYPE_ATAPI: 160 case IF_TYPE_ATAPI:
161 sprintf ((char *)info->name, "hd%c%d", 161 sprintf ((char *)info->name, "hd%c%d",
162 'a' + dev_desc->dev, part_num); 162 'a' + dev_desc->dev, part_num);
163 break; 163 break;
164 case IF_TYPE_SCSI: 164 case IF_TYPE_SCSI:
165 sprintf ((char *)info->name, "sd%c%d", 165 sprintf ((char *)info->name, "sd%c%d",
166 'a' + dev_desc->dev, part_num); 166 'a' + dev_desc->dev, part_num);
167 break; 167 break;
168 case IF_TYPE_USB: 168 case IF_TYPE_USB:
169 sprintf ((char *)info->name, "usbd%c%d", 169 sprintf ((char *)info->name, "usbd%c%d",
170 'a' + dev_desc->dev, part_num); 170 'a' + dev_desc->dev, part_num);
171 break; 171 break;
172 case IF_TYPE_DOC: 172 case IF_TYPE_DOC:
173 sprintf ((char *)info->name, "docd%c%d", 173 sprintf ((char *)info->name, "docd%c%d",
174 'a' + dev_desc->dev, part_num); 174 'a' + dev_desc->dev, part_num);
175 break; 175 break;
176 default: 176 default:
177 sprintf ((char *)info->name, "xx%c%d", 177 sprintf ((char *)info->name, "xx%c%d",
178 'a' + dev_desc->dev, part_num); 178 'a' + dev_desc->dev, part_num);
179 break; 179 break;
180 } 180 }
181 /* the bootcatalog (including validation Entry) is limited to 2048Bytes 181 /* the bootcatalog (including validation Entry) is limited to 2048Bytes
182 * (63 boot entries + validation entry) */ 182 * (63 boot entries + validation entry) */
183 while(offset<2048) { 183 while(offset<2048) {
184 pide=(iso_init_def_entry_t *)&tmpbuf[offset]; 184 pide=(iso_init_def_entry_t *)&tmpbuf[offset];
185 if ((pide->boot_ind==0x88) || 185 if ((pide->boot_ind==0x88) ||
186 (pide->boot_ind==0x00)) { /* Header Id for default Sections Entries */ 186 (pide->boot_ind==0x00)) { /* Header Id for default Sections Entries */
187 if(entry_num==part_num) { /* part found */ 187 if(entry_num==part_num) { /* part found */
188 goto found; 188 goto found;
189 } 189 }
190 entry_num++; /* count partitions Entries (boot and non bootables */ 190 entry_num++; /* count partitions Entries (boot and non bootables */
191 offset+=0x20; 191 offset+=0x20;
192 continue; 192 continue;
193 } 193 }
194 if ((pide->boot_ind==0x90) || /* Section Header Entry */ 194 if ((pide->boot_ind==0x90) || /* Section Header Entry */
195 (pide->boot_ind==0x91) || /* Section Header Entry (last) */ 195 (pide->boot_ind==0x91) || /* Section Header Entry (last) */
196 (pide->boot_ind==0x44)) { /* Extension Indicator */ 196 (pide->boot_ind==0x44)) { /* Extension Indicator */
197 offset+=0x20; /* skip unused entries */ 197 offset+=0x20; /* skip unused entries */
198 } 198 }
199 else { 199 else {
200 if(verb) 200 if(verb)
201 printf ("** Partition %d not found on device %d **\n", 201 printf ("** Partition %d not found on device %d **\n",
202 part_num,dev_desc->dev); 202 part_num,dev_desc->dev);
203 return(-1); 203 return(-1);
204 } 204 }
205 } 205 }
206 /* if we reach this point entire sector has been 206 /* if we reach this point entire sector has been
207 * searched w/o succsess */ 207 * searched w/o succsess */
208 if(verb) 208 if(verb)
209 printf ("** Partition %d not found on device %d **\n", 209 printf ("** Partition %d not found on device %d **\n",
210 part_num,dev_desc->dev); 210 part_num,dev_desc->dev);
211 return(-1); 211 return(-1);
212 found: 212 found:
213 if(pide->boot_ind!=0x88) { 213 if(pide->boot_ind!=0x88) {
214 if(verb) 214 if(verb)
215 printf ("** Partition %d is not bootable on device %d **\n", 215 printf ("** Partition %d is not bootable on device %d **\n",
216 part_num,dev_desc->dev); 216 part_num,dev_desc->dev);
217 return (-1); 217 return (-1);
218 } 218 }
219 switch(pide->boot_media) { 219 switch(pide->boot_media) {
220 case 0x00: /* no emulation */ 220 case 0x00: /* no emulation */
221 info->size=le16_to_int(pide->sec_cnt)>>2; 221 info->size=le16_to_int(pide->sec_cnt)>>2;
222 break; 222 break;
223 case 0x01: info->size=2400>>2; break; /* 1.2MByte Floppy */ 223 case 0x01: info->size=2400>>2; break; /* 1.2MByte Floppy */
224 case 0x02: info->size=2880>>2; break; /* 1.44MByte Floppy */ 224 case 0x02: info->size=2880>>2; break; /* 1.44MByte Floppy */
225 case 0x03: info->size=5760>>2; break; /* 2.88MByte Floppy */ 225 case 0x03: info->size=5760>>2; break; /* 2.88MByte Floppy */
226 case 0x04: info->size=2880>>2; break; /* dummy (HD Emulation) */ 226 case 0x04: info->size=2880>>2; break; /* dummy (HD Emulation) */
227 default: info->size=0; break; 227 default: info->size=0; break;
228 } 228 }
229 newblkaddr=le32_to_int(pide->rel_block_addr); 229 newblkaddr=le32_to_int(pide->rel_block_addr);
230 info->start=newblkaddr; 230 info->start=newblkaddr;
231 PRINTF(" part %d found @ %lx size %lx\n",part_num,newblkaddr,info->size); 231 PRINTF(" part %d found @ %lx size %lx\n",part_num,newblkaddr,info->size);
232 return 0; 232 return 0;
233 } 233 }
234 234
235 int get_partition_info_iso(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info) 235 int get_partition_info_iso(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info)
236 { 236 {
237 return(get_partition_info_iso_verb(dev_desc, part_num, info, 1)); 237 return(get_partition_info_iso_verb(dev_desc, part_num, info, 1));
238 } 238 }
239 239
240 240
241 void print_part_iso(block_dev_desc_t * dev_desc) 241 void print_part_iso(block_dev_desc_t * dev_desc)
242 { 242 {
243 disk_partition_t info; 243 disk_partition_t info;
244 int i; 244 int i;
245 if(get_partition_info_iso_verb(dev_desc,0,&info,0)==-1) { 245 if(get_partition_info_iso_verb(dev_desc,0,&info,0)==-1) {
246 printf("** No boot partition found on device %d **\n",dev_desc->dev); 246 printf("** No boot partition found on device %d **\n",dev_desc->dev);
247 return; 247 return;
248 } 248 }
249 printf("Part Start Sect x Size Type\n"); 249 printf("Part Start Sect x Size Type\n");
250 i=0; 250 i=0;
251 do { 251 do {
252 printf (" %2d %8ld %8ld %6ld %.32s\n", 252 printf(" %2d " LBAFU " " LBAFU " %6ld %.32s\n",
253 i, info.start, info.size, info.blksz, info.type); 253 i, info.start, info.size, info.blksz, info.type);
254 i++; 254 i++;
255 } while (get_partition_info_iso_verb(dev_desc,i,&info,0)!=-1); 255 } while (get_partition_info_iso_verb(dev_desc,i,&info,0)!=-1);
256 } 256 }
257 257
258 int test_part_iso (block_dev_desc_t *dev_desc) 258 int test_part_iso (block_dev_desc_t *dev_desc)
259 { 259 {
260 disk_partition_t info; 260 disk_partition_t info;
261 261
262 return(get_partition_info_iso_verb(dev_desc,0,&info,0)); 262 return(get_partition_info_iso_verb(dev_desc,0,&info,0));
263 } 263 }
264 264
265 #endif 265 #endif
266 266
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * made from existing ext2/dev.c file of Uboot 7 * made from existing ext2/dev.c file of Uboot
8 * (C) Copyright 2004 8 * (C) Copyright 2004
9 * esd gmbh <www.esd-electronics.com> 9 * esd gmbh <www.esd-electronics.com>
10 * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 10 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
11 * 11 *
12 * based on code of fs/reiserfs/dev.c by 12 * based on code of fs/reiserfs/dev.c by
13 * 13 *
14 * (C) Copyright 2003 - 2004 14 * (C) Copyright 2003 - 2004
15 * Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com> 15 * Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
16 * 16 *
17 * This program is free software; you can redistribute it and/or modify 17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by 18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or 19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version. 20 * (at your option) any later version.
21 * 21 *
22 * This program is distributed in the hope that it will be useful, 22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details. 25 * GNU General Public License for more details.
26 * 26 *
27 * You should have received a copy of the GNU General Public License 27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software 28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 * 30 *
31 */ 31 */
32 32
33 /* 33 /*
34 * Changelog: 34 * Changelog:
35 * 0.1 - Newly created file for ext4fs support. Taken from 35 * 0.1 - Newly created file for ext4fs support. Taken from
36 * fs/ext2/dev.c file in uboot. 36 * fs/ext2/dev.c file in uboot.
37 */ 37 */
38 38
39 #include <common.h> 39 #include <common.h>
40 #include <config.h> 40 #include <config.h>
41 #include <ext4fs.h> 41 #include <ext4fs.h>
42 #include <ext_common.h> 42 #include <ext_common.h>
43 #include "ext4_common.h" 43 #include "ext4_common.h"
44 44
45 unsigned long part_offset; 45 lbaint_t part_offset;
46 46
47 static block_dev_desc_t *ext4fs_block_dev_desc; 47 static block_dev_desc_t *ext4fs_block_dev_desc;
48 static disk_partition_t *part_info; 48 static disk_partition_t *part_info;
49 49
50 void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info) 50 void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info)
51 { 51 {
52 assert(rbdd->blksz == (1 << rbdd->log2blksz)); 52 assert(rbdd->blksz == (1 << rbdd->log2blksz));
53 ext4fs_block_dev_desc = rbdd; 53 ext4fs_block_dev_desc = rbdd;
54 get_fs()->dev_desc = rbdd; 54 get_fs()->dev_desc = rbdd;
55 part_info = info; 55 part_info = info;
56 part_offset = info->start; 56 part_offset = info->start;
57 get_fs()->total_sect = (info->size * info->blksz) >> 57 get_fs()->total_sect = (info->size * info->blksz) >>
58 get_fs()->dev_desc->log2blksz; 58 get_fs()->dev_desc->log2blksz;
59 } 59 }
60 60
61 int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf) 61 int ext4fs_devread(lbaint_t sector, int byte_offset, int byte_len, char *buf)
62 { 62 {
63 unsigned block_len; 63 unsigned block_len;
64 int log2blksz = ext4fs_block_dev_desc->log2blksz; 64 int log2blksz = ext4fs_block_dev_desc->log2blksz;
65 ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, (ext4fs_block_dev_desc ? 65 ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, (ext4fs_block_dev_desc ?
66 ext4fs_block_dev_desc->blksz : 66 ext4fs_block_dev_desc->blksz :
67 0)); 67 0));
68 if (ext4fs_block_dev_desc == NULL) { 68 if (ext4fs_block_dev_desc == NULL) {
69 printf("** Invalid Block Device Descriptor (NULL)\n"); 69 printf("** Invalid Block Device Descriptor (NULL)\n");
70 return 0; 70 return 0;
71 } 71 }
72 72
73 /* Check partition boundaries */ 73 /* Check partition boundaries */
74 if ((sector < 0) || 74 if ((sector < 0) ||
75 ((sector + ((byte_offset + byte_len - 1) >> log2blksz)) 75 ((sector + ((byte_offset + byte_len - 1) >> log2blksz))
76 >= part_info->size)) { 76 >= part_info->size)) {
77 printf("%s read outside partition %d\n", __func__, sector); 77 printf("%s read outside partition " LBAFU "\n", __func__,
78 sector);
78 return 0; 79 return 0;
79 } 80 }
80 81
81 /* Get the read to the beginning of a partition */ 82 /* Get the read to the beginning of a partition */
82 sector += byte_offset >> log2blksz; 83 sector += byte_offset >> log2blksz;
83 byte_offset &= ext4fs_block_dev_desc->blksz - 1; 84 byte_offset &= ext4fs_block_dev_desc->blksz - 1;
84 85
85 debug(" <%d, %d, %d>\n", sector, byte_offset, byte_len); 86 debug(" <" LBAFU ", %d, %d>\n", sector, byte_offset, byte_len);
86 87
87 if (byte_offset != 0) { 88 if (byte_offset != 0) {
88 /* read first part which isn't aligned with start of sector */ 89 /* read first part which isn't aligned with start of sector */
89 if (ext4fs_block_dev_desc-> 90 if (ext4fs_block_dev_desc->
90 block_read(ext4fs_block_dev_desc->dev, 91 block_read(ext4fs_block_dev_desc->dev,
91 part_info->start + sector, 1, 92 part_info->start + sector, 1,
92 (unsigned long *) sec_buf) != 1) { 93 (unsigned long *) sec_buf) != 1) {
93 printf(" ** ext2fs_devread() read error **\n"); 94 printf(" ** ext2fs_devread() read error **\n");
94 return 0; 95 return 0;
95 } 96 }
96 memcpy(buf, sec_buf + byte_offset, 97 memcpy(buf, sec_buf + byte_offset,
97 min(ext4fs_block_dev_desc->blksz 98 min(ext4fs_block_dev_desc->blksz
98 - byte_offset, byte_len)); 99 - byte_offset, byte_len));
99 buf += min(ext4fs_block_dev_desc->blksz 100 buf += min(ext4fs_block_dev_desc->blksz
100 - byte_offset, byte_len); 101 - byte_offset, byte_len);
101 byte_len -= min(ext4fs_block_dev_desc->blksz 102 byte_len -= min(ext4fs_block_dev_desc->blksz
102 - byte_offset, byte_len); 103 - byte_offset, byte_len);
103 sector++; 104 sector++;
104 } 105 }
105 106
106 if (byte_len == 0) 107 if (byte_len == 0)
107 return 1; 108 return 1;
108 109
109 /* read sector aligned part */ 110 /* read sector aligned part */
110 block_len = byte_len & ~(ext4fs_block_dev_desc->blksz - 1); 111 block_len = byte_len & ~(ext4fs_block_dev_desc->blksz - 1);
111 112
112 if (block_len == 0) { 113 if (block_len == 0) {
113 ALLOC_CACHE_ALIGN_BUFFER(u8, p, ext4fs_block_dev_desc->blksz); 114 ALLOC_CACHE_ALIGN_BUFFER(u8, p, ext4fs_block_dev_desc->blksz);
114 115
115 block_len = ext4fs_block_dev_desc->blksz; 116 block_len = ext4fs_block_dev_desc->blksz;
116 ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev, 117 ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev,
117 part_info->start + sector, 118 part_info->start + sector,
118 1, (unsigned long *)p); 119 1, (unsigned long *)p);
119 memcpy(buf, p, byte_len); 120 memcpy(buf, p, byte_len);
120 return 1; 121 return 1;
121 } 122 }
122 123
123 if (ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev, 124 if (ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev,
124 part_info->start + sector, 125 part_info->start + sector,
125 block_len >> log2blksz, 126 block_len >> log2blksz,
126 (unsigned long *) buf) != 127 (unsigned long *) buf) !=
127 block_len >> log2blksz) { 128 block_len >> log2blksz) {
128 printf(" ** %s read error - block\n", __func__); 129 printf(" ** %s read error - block\n", __func__);
129 return 0; 130 return 0;
130 } 131 }
131 block_len = byte_len & ~(ext4fs_block_dev_desc->blksz - 1); 132 block_len = byte_len & ~(ext4fs_block_dev_desc->blksz - 1);
132 buf += block_len; 133 buf += block_len;
133 byte_len -= block_len; 134 byte_len -= block_len;
134 sector += block_len / ext4fs_block_dev_desc->blksz; 135 sector += block_len / ext4fs_block_dev_desc->blksz;
135 136
136 if (byte_len != 0) { 137 if (byte_len != 0) {
137 /* read rest of data which are not in whole sector */ 138 /* read rest of data which are not in whole sector */
138 if (ext4fs_block_dev_desc-> 139 if (ext4fs_block_dev_desc->
139 block_read(ext4fs_block_dev_desc->dev, 140 block_read(ext4fs_block_dev_desc->dev,
140 part_info->start + sector, 1, 141 part_info->start + sector, 1,
141 (unsigned long *) sec_buf) != 1) { 142 (unsigned long *) sec_buf) != 1) {
142 printf("* %s read error - last part\n", __func__); 143 printf("* %s read error - last part\n", __func__);
143 return 0; 144 return 0;
144 } 145 }
145 memcpy(buf, sec_buf, byte_len); 146 memcpy(buf, sec_buf, byte_len);
146 } 147 }
147 return 1; 148 return 1;
148 } 149 }
149 150
150 int ext4_read_superblock(char *buffer) 151 int ext4_read_superblock(char *buffer)
151 { 152 {
152 struct ext_filesystem *fs = get_fs(); 153 struct ext_filesystem *fs = get_fs();
153 int sect = SUPERBLOCK_START >> fs->dev_desc->log2blksz; 154 int sect = SUPERBLOCK_START >> fs->dev_desc->log2blksz;
154 int off = SUPERBLOCK_START % fs->dev_desc->blksz; 155 int off = SUPERBLOCK_START % fs->dev_desc->blksz;
155 156
156 return ext4fs_devread(sect, off, SUPERBLOCK_SIZE, 157 return ext4fs_devread(sect, off, SUPERBLOCK_SIZE,
157 buffer); 158 buffer);
158 } 159 }
159 160
fs/ext4/ext4_common.c
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * ext4ls and ext4load : Based on ext2 ls load support in Uboot. 7 * ext4ls and ext4load : Based on ext2 ls load support in Uboot.
8 * 8 *
9 * (C) Copyright 2004 9 * (C) Copyright 2004
10 * esd gmbh <www.esd-electronics.com> 10 * esd gmbh <www.esd-electronics.com>
11 * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 11 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
12 * 12 *
13 * based on code from grub2 fs/ext2.c and fs/fshelp.c by 13 * based on code from grub2 fs/ext2.c and fs/fshelp.c by
14 * GRUB -- GRand Unified Bootloader 14 * GRUB -- GRand Unified Bootloader
15 * Copyright (C) 2003, 2004 Free Software Foundation, Inc. 15 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
16 * 16 *
17 * ext4write : Based on generic ext4 protocol. 17 * ext4write : Based on generic ext4 protocol.
18 * 18 *
19 * This program is free software; you can redistribute it and/or modify 19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by 20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or 21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version. 22 * (at your option) any later version.
23 * 23 *
24 * This program is distributed in the hope that it will be useful, 24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details. 27 * GNU General Public License for more details.
28 * 28 *
29 * You should have received a copy of the GNU General Public License 29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software 30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 31 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 */ 32 */
33 33
34 #include <common.h> 34 #include <common.h>
35 #include <ext_common.h> 35 #include <ext_common.h>
36 #include <ext4fs.h> 36 #include <ext4fs.h>
37 #include <malloc.h> 37 #include <malloc.h>
38 #include <stddef.h> 38 #include <stddef.h>
39 #include <linux/stat.h> 39 #include <linux/stat.h>
40 #include <linux/time.h> 40 #include <linux/time.h>
41 #include <asm/byteorder.h> 41 #include <asm/byteorder.h>
42 #include "ext4_common.h" 42 #include "ext4_common.h"
43 43
44 struct ext2_data *ext4fs_root; 44 struct ext2_data *ext4fs_root;
45 struct ext2fs_node *ext4fs_file; 45 struct ext2fs_node *ext4fs_file;
46 uint32_t *ext4fs_indir1_block; 46 uint32_t *ext4fs_indir1_block;
47 int ext4fs_indir1_size; 47 int ext4fs_indir1_size;
48 int ext4fs_indir1_blkno = -1; 48 int ext4fs_indir1_blkno = -1;
49 uint32_t *ext4fs_indir2_block; 49 uint32_t *ext4fs_indir2_block;
50 int ext4fs_indir2_size; 50 int ext4fs_indir2_size;
51 int ext4fs_indir2_blkno = -1; 51 int ext4fs_indir2_blkno = -1;
52 52
53 uint32_t *ext4fs_indir3_block; 53 uint32_t *ext4fs_indir3_block;
54 int ext4fs_indir3_size; 54 int ext4fs_indir3_size;
55 int ext4fs_indir3_blkno = -1; 55 int ext4fs_indir3_blkno = -1;
56 struct ext2_inode *g_parent_inode; 56 struct ext2_inode *g_parent_inode;
57 static int symlinknest; 57 static int symlinknest;
58 58
59 #if defined(CONFIG_EXT4_WRITE) 59 #if defined(CONFIG_EXT4_WRITE)
60 uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n) 60 uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n)
61 { 61 {
62 uint32_t res = size / n; 62 uint32_t res = size / n;
63 if (res * n != size) 63 if (res * n != size)
64 res++; 64 res++;
65 65
66 return res; 66 return res;
67 } 67 }
68 68
69 void put_ext4(uint64_t off, void *buf, uint32_t size) 69 void put_ext4(uint64_t off, void *buf, uint32_t size)
70 { 70 {
71 uint64_t startblock; 71 uint64_t startblock;
72 uint64_t remainder; 72 uint64_t remainder;
73 unsigned char *temp_ptr = NULL; 73 unsigned char *temp_ptr = NULL;
74 struct ext_filesystem *fs = get_fs(); 74 struct ext_filesystem *fs = get_fs();
75 int log2blksz = fs->dev_desc->log2blksz; 75 int log2blksz = fs->dev_desc->log2blksz;
76 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, fs->dev_desc->blksz); 76 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, fs->dev_desc->blksz);
77 77
78 startblock = off >> log2blksz; 78 startblock = off >> log2blksz;
79 startblock += part_offset; 79 startblock += part_offset;
80 remainder = off & (uint64_t)(fs->dev_desc->blksz - 1); 80 remainder = off & (uint64_t)(fs->dev_desc->blksz - 1);
81 81
82 if (fs->dev_desc == NULL) 82 if (fs->dev_desc == NULL)
83 return; 83 return;
84 84
85 if ((startblock + (size >> log2blksz)) > 85 if ((startblock + (size >> log2blksz)) >
86 (part_offset + fs->total_sect)) { 86 (part_offset + fs->total_sect)) {
87 printf("part_offset is %lu\n", part_offset); 87 printf("part_offset is " LBAFU "\n", part_offset);
88 printf("total_sector is %llu\n", fs->total_sect); 88 printf("total_sector is %llu\n", fs->total_sect);
89 printf("error: overflow occurs\n"); 89 printf("error: overflow occurs\n");
90 return; 90 return;
91 } 91 }
92 92
93 if (remainder) { 93 if (remainder) {
94 if (fs->dev_desc->block_read) { 94 if (fs->dev_desc->block_read) {
95 fs->dev_desc->block_read(fs->dev_desc->dev, 95 fs->dev_desc->block_read(fs->dev_desc->dev,
96 startblock, 1, sec_buf); 96 startblock, 1, sec_buf);
97 temp_ptr = sec_buf; 97 temp_ptr = sec_buf;
98 memcpy((temp_ptr + remainder), 98 memcpy((temp_ptr + remainder),
99 (unsigned char *)buf, size); 99 (unsigned char *)buf, size);
100 fs->dev_desc->block_write(fs->dev_desc->dev, 100 fs->dev_desc->block_write(fs->dev_desc->dev,
101 startblock, 1, sec_buf); 101 startblock, 1, sec_buf);
102 } 102 }
103 } else { 103 } else {
104 if (size >> log2blksz != 0) { 104 if (size >> log2blksz != 0) {
105 fs->dev_desc->block_write(fs->dev_desc->dev, 105 fs->dev_desc->block_write(fs->dev_desc->dev,
106 startblock, 106 startblock,
107 size >> log2blksz, 107 size >> log2blksz,
108 (unsigned long *)buf); 108 (unsigned long *)buf);
109 } else { 109 } else {
110 fs->dev_desc->block_read(fs->dev_desc->dev, 110 fs->dev_desc->block_read(fs->dev_desc->dev,
111 startblock, 1, sec_buf); 111 startblock, 1, sec_buf);
112 temp_ptr = sec_buf; 112 temp_ptr = sec_buf;
113 memcpy(temp_ptr, buf, size); 113 memcpy(temp_ptr, buf, size);
114 fs->dev_desc->block_write(fs->dev_desc->dev, 114 fs->dev_desc->block_write(fs->dev_desc->dev,
115 startblock, 1, 115 startblock, 1,
116 (unsigned long *)sec_buf); 116 (unsigned long *)sec_buf);
117 } 117 }
118 } 118 }
119 } 119 }
120 120
121 static int _get_new_inode_no(unsigned char *buffer) 121 static int _get_new_inode_no(unsigned char *buffer)
122 { 122 {
123 struct ext_filesystem *fs = get_fs(); 123 struct ext_filesystem *fs = get_fs();
124 unsigned char input; 124 unsigned char input;
125 int operand, status; 125 int operand, status;
126 int count = 1; 126 int count = 1;
127 int j = 0; 127 int j = 0;
128 128
129 /* get the blocksize of the filesystem */ 129 /* get the blocksize of the filesystem */
130 unsigned char *ptr = buffer; 130 unsigned char *ptr = buffer;
131 while (*ptr == 255) { 131 while (*ptr == 255) {
132 ptr++; 132 ptr++;
133 count += 8; 133 count += 8;
134 if (count > ext4fs_root->sblock.inodes_per_group) 134 if (count > ext4fs_root->sblock.inodes_per_group)
135 return -1; 135 return -1;
136 } 136 }
137 137
138 for (j = 0; j < fs->blksz; j++) { 138 for (j = 0; j < fs->blksz; j++) {
139 input = *ptr; 139 input = *ptr;
140 int i = 0; 140 int i = 0;
141 while (i <= 7) { 141 while (i <= 7) {
142 operand = 1 << i; 142 operand = 1 << i;
143 status = input & operand; 143 status = input & operand;
144 if (status) { 144 if (status) {
145 i++; 145 i++;
146 count++; 146 count++;
147 } else { 147 } else {
148 *ptr |= operand; 148 *ptr |= operand;
149 return count; 149 return count;
150 } 150 }
151 } 151 }
152 ptr = ptr + 1; 152 ptr = ptr + 1;
153 } 153 }
154 154
155 return -1; 155 return -1;
156 } 156 }
157 157
158 static int _get_new_blk_no(unsigned char *buffer) 158 static int _get_new_blk_no(unsigned char *buffer)
159 { 159 {
160 unsigned char input; 160 unsigned char input;
161 int operand, status; 161 int operand, status;
162 int count = 0; 162 int count = 0;
163 int j = 0; 163 int j = 0;
164 unsigned char *ptr = buffer; 164 unsigned char *ptr = buffer;
165 struct ext_filesystem *fs = get_fs(); 165 struct ext_filesystem *fs = get_fs();
166 166
167 if (fs->blksz != 1024) 167 if (fs->blksz != 1024)
168 count = 0; 168 count = 0;
169 else 169 else
170 count = 1; 170 count = 1;
171 171
172 while (*ptr == 255) { 172 while (*ptr == 255) {
173 ptr++; 173 ptr++;
174 count += 8; 174 count += 8;
175 if (count == (fs->blksz * 8)) 175 if (count == (fs->blksz * 8))
176 return -1; 176 return -1;
177 } 177 }
178 178
179 for (j = 0; j < fs->blksz; j++) { 179 for (j = 0; j < fs->blksz; j++) {
180 input = *ptr; 180 input = *ptr;
181 int i = 0; 181 int i = 0;
182 while (i <= 7) { 182 while (i <= 7) {
183 operand = 1 << i; 183 operand = 1 << i;
184 status = input & operand; 184 status = input & operand;
185 if (status) { 185 if (status) {
186 i++; 186 i++;
187 count++; 187 count++;
188 } else { 188 } else {
189 *ptr |= operand; 189 *ptr |= operand;
190 return count; 190 return count;
191 } 191 }
192 } 192 }
193 ptr = ptr + 1; 193 ptr = ptr + 1;
194 } 194 }
195 195
196 return -1; 196 return -1;
197 } 197 }
198 198
199 int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index) 199 int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index)
200 { 200 {
201 int i, remainder, status; 201 int i, remainder, status;
202 unsigned char *ptr = buffer; 202 unsigned char *ptr = buffer;
203 unsigned char operand; 203 unsigned char operand;
204 i = blockno / 8; 204 i = blockno / 8;
205 remainder = blockno % 8; 205 remainder = blockno % 8;
206 int blocksize = EXT2_BLOCK_SIZE(ext4fs_root); 206 int blocksize = EXT2_BLOCK_SIZE(ext4fs_root);
207 207
208 i = i - (index * blocksize); 208 i = i - (index * blocksize);
209 if (blocksize != 1024) { 209 if (blocksize != 1024) {
210 ptr = ptr + i; 210 ptr = ptr + i;
211 operand = 1 << remainder; 211 operand = 1 << remainder;
212 status = *ptr & operand; 212 status = *ptr & operand;
213 if (status) 213 if (status)
214 return -1; 214 return -1;
215 215
216 *ptr = *ptr | operand; 216 *ptr = *ptr | operand;
217 return 0; 217 return 0;
218 } else { 218 } else {
219 if (remainder == 0) { 219 if (remainder == 0) {
220 ptr = ptr + i - 1; 220 ptr = ptr + i - 1;
221 operand = (1 << 7); 221 operand = (1 << 7);
222 } else { 222 } else {
223 ptr = ptr + i; 223 ptr = ptr + i;
224 operand = (1 << (remainder - 1)); 224 operand = (1 << (remainder - 1));
225 } 225 }
226 status = *ptr & operand; 226 status = *ptr & operand;
227 if (status) 227 if (status)
228 return -1; 228 return -1;
229 229
230 *ptr = *ptr | operand; 230 *ptr = *ptr | operand;
231 return 0; 231 return 0;
232 } 232 }
233 } 233 }
234 234
235 void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, int index) 235 void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, int index)
236 { 236 {
237 int i, remainder, status; 237 int i, remainder, status;
238 unsigned char *ptr = buffer; 238 unsigned char *ptr = buffer;
239 unsigned char operand; 239 unsigned char operand;
240 i = blockno / 8; 240 i = blockno / 8;
241 remainder = blockno % 8; 241 remainder = blockno % 8;
242 int blocksize = EXT2_BLOCK_SIZE(ext4fs_root); 242 int blocksize = EXT2_BLOCK_SIZE(ext4fs_root);
243 243
244 i = i - (index * blocksize); 244 i = i - (index * blocksize);
245 if (blocksize != 1024) { 245 if (blocksize != 1024) {
246 ptr = ptr + i; 246 ptr = ptr + i;
247 operand = (1 << remainder); 247 operand = (1 << remainder);
248 status = *ptr & operand; 248 status = *ptr & operand;
249 if (status) 249 if (status)
250 *ptr = *ptr & ~(operand); 250 *ptr = *ptr & ~(operand);
251 } else { 251 } else {
252 if (remainder == 0) { 252 if (remainder == 0) {
253 ptr = ptr + i - 1; 253 ptr = ptr + i - 1;
254 operand = (1 << 7); 254 operand = (1 << 7);
255 } else { 255 } else {
256 ptr = ptr + i; 256 ptr = ptr + i;
257 operand = (1 << (remainder - 1)); 257 operand = (1 << (remainder - 1));
258 } 258 }
259 status = *ptr & operand; 259 status = *ptr & operand;
260 if (status) 260 if (status)
261 *ptr = *ptr & ~(operand); 261 *ptr = *ptr & ~(operand);
262 } 262 }
263 } 263 }
264 264
265 int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index) 265 int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index)
266 { 266 {
267 int i, remainder, status; 267 int i, remainder, status;
268 unsigned char *ptr = buffer; 268 unsigned char *ptr = buffer;
269 unsigned char operand; 269 unsigned char operand;
270 270
271 inode_no -= (index * ext4fs_root->sblock.inodes_per_group); 271 inode_no -= (index * ext4fs_root->sblock.inodes_per_group);
272 i = inode_no / 8; 272 i = inode_no / 8;
273 remainder = inode_no % 8; 273 remainder = inode_no % 8;
274 if (remainder == 0) { 274 if (remainder == 0) {
275 ptr = ptr + i - 1; 275 ptr = ptr + i - 1;
276 operand = (1 << 7); 276 operand = (1 << 7);
277 } else { 277 } else {
278 ptr = ptr + i; 278 ptr = ptr + i;
279 operand = (1 << (remainder - 1)); 279 operand = (1 << (remainder - 1));
280 } 280 }
281 status = *ptr & operand; 281 status = *ptr & operand;
282 if (status) 282 if (status)
283 return -1; 283 return -1;
284 284
285 *ptr = *ptr | operand; 285 *ptr = *ptr | operand;
286 286
287 return 0; 287 return 0;
288 } 288 }
289 289
290 void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index) 290 void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index)
291 { 291 {
292 int i, remainder, status; 292 int i, remainder, status;
293 unsigned char *ptr = buffer; 293 unsigned char *ptr = buffer;
294 unsigned char operand; 294 unsigned char operand;
295 295
296 inode_no -= (index * ext4fs_root->sblock.inodes_per_group); 296 inode_no -= (index * ext4fs_root->sblock.inodes_per_group);
297 i = inode_no / 8; 297 i = inode_no / 8;
298 remainder = inode_no % 8; 298 remainder = inode_no % 8;
299 if (remainder == 0) { 299 if (remainder == 0) {
300 ptr = ptr + i - 1; 300 ptr = ptr + i - 1;
301 operand = (1 << 7); 301 operand = (1 << 7);
302 } else { 302 } else {
303 ptr = ptr + i; 303 ptr = ptr + i;
304 operand = (1 << (remainder - 1)); 304 operand = (1 << (remainder - 1));
305 } 305 }
306 status = *ptr & operand; 306 status = *ptr & operand;
307 if (status) 307 if (status)
308 *ptr = *ptr & ~(operand); 308 *ptr = *ptr & ~(operand);
309 } 309 }
310 310
311 int ext4fs_checksum_update(unsigned int i) 311 int ext4fs_checksum_update(unsigned int i)
312 { 312 {
313 struct ext2_block_group *desc; 313 struct ext2_block_group *desc;
314 struct ext_filesystem *fs = get_fs(); 314 struct ext_filesystem *fs = get_fs();
315 __u16 crc = 0; 315 __u16 crc = 0;
316 316
317 desc = (struct ext2_block_group *)&fs->bgd[i]; 317 desc = (struct ext2_block_group *)&fs->bgd[i];
318 if (fs->sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { 318 if (fs->sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
319 int offset = offsetof(struct ext2_block_group, bg_checksum); 319 int offset = offsetof(struct ext2_block_group, bg_checksum);
320 320
321 crc = ext2fs_crc16(~0, fs->sb->unique_id, 321 crc = ext2fs_crc16(~0, fs->sb->unique_id,
322 sizeof(fs->sb->unique_id)); 322 sizeof(fs->sb->unique_id));
323 crc = ext2fs_crc16(crc, &i, sizeof(i)); 323 crc = ext2fs_crc16(crc, &i, sizeof(i));
324 crc = ext2fs_crc16(crc, desc, offset); 324 crc = ext2fs_crc16(crc, desc, offset);
325 offset += sizeof(desc->bg_checksum); /* skip checksum */ 325 offset += sizeof(desc->bg_checksum); /* skip checksum */
326 assert(offset == sizeof(*desc)); 326 assert(offset == sizeof(*desc));
327 } 327 }
328 328
329 return crc; 329 return crc;
330 } 330 }
331 331
332 static int check_void_in_dentry(struct ext2_dirent *dir, char *filename) 332 static int check_void_in_dentry(struct ext2_dirent *dir, char *filename)
333 { 333 {
334 int dentry_length; 334 int dentry_length;
335 int sizeof_void_space; 335 int sizeof_void_space;
336 int new_entry_byte_reqd; 336 int new_entry_byte_reqd;
337 short padding_factor = 0; 337 short padding_factor = 0;
338 338
339 if (dir->namelen % 4 != 0) 339 if (dir->namelen % 4 != 0)
340 padding_factor = 4 - (dir->namelen % 4); 340 padding_factor = 4 - (dir->namelen % 4);
341 341
342 dentry_length = sizeof(struct ext2_dirent) + 342 dentry_length = sizeof(struct ext2_dirent) +
343 dir->namelen + padding_factor; 343 dir->namelen + padding_factor;
344 sizeof_void_space = dir->direntlen - dentry_length; 344 sizeof_void_space = dir->direntlen - dentry_length;
345 if (sizeof_void_space == 0) 345 if (sizeof_void_space == 0)
346 return 0; 346 return 0;
347 347
348 padding_factor = 0; 348 padding_factor = 0;
349 if (strlen(filename) % 4 != 0) 349 if (strlen(filename) % 4 != 0)
350 padding_factor = 4 - (strlen(filename) % 4); 350 padding_factor = 4 - (strlen(filename) % 4);
351 351
352 new_entry_byte_reqd = strlen(filename) + 352 new_entry_byte_reqd = strlen(filename) +
353 sizeof(struct ext2_dirent) + padding_factor; 353 sizeof(struct ext2_dirent) + padding_factor;
354 if (sizeof_void_space >= new_entry_byte_reqd) { 354 if (sizeof_void_space >= new_entry_byte_reqd) {
355 dir->direntlen = dentry_length; 355 dir->direntlen = dentry_length;
356 return sizeof_void_space; 356 return sizeof_void_space;
357 } 357 }
358 358
359 return 0; 359 return 0;
360 } 360 }
361 361
362 void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type) 362 void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type)
363 { 363 {
364 unsigned int *zero_buffer = NULL; 364 unsigned int *zero_buffer = NULL;
365 char *root_first_block_buffer = NULL; 365 char *root_first_block_buffer = NULL;
366 int direct_blk_idx; 366 int direct_blk_idx;
367 long int root_blknr; 367 long int root_blknr;
368 long int first_block_no_of_root = 0; 368 long int first_block_no_of_root = 0;
369 long int previous_blknr = -1; 369 long int previous_blknr = -1;
370 int totalbytes = 0; 370 int totalbytes = 0;
371 short int padding_factor = 0; 371 short int padding_factor = 0;
372 unsigned int new_entry_byte_reqd; 372 unsigned int new_entry_byte_reqd;
373 unsigned int last_entry_dirlen; 373 unsigned int last_entry_dirlen;
374 int sizeof_void_space = 0; 374 int sizeof_void_space = 0;
375 int templength = 0; 375 int templength = 0;
376 int inodeno; 376 int inodeno;
377 int status; 377 int status;
378 struct ext_filesystem *fs = get_fs(); 378 struct ext_filesystem *fs = get_fs();
379 /* directory entry */ 379 /* directory entry */
380 struct ext2_dirent *dir; 380 struct ext2_dirent *dir;
381 char *temp_dir = NULL; 381 char *temp_dir = NULL;
382 382
383 zero_buffer = zalloc(fs->blksz); 383 zero_buffer = zalloc(fs->blksz);
384 if (!zero_buffer) { 384 if (!zero_buffer) {
385 printf("No Memory\n"); 385 printf("No Memory\n");
386 return; 386 return;
387 } 387 }
388 root_first_block_buffer = zalloc(fs->blksz); 388 root_first_block_buffer = zalloc(fs->blksz);
389 if (!root_first_block_buffer) { 389 if (!root_first_block_buffer) {
390 free(zero_buffer); 390 free(zero_buffer);
391 printf("No Memory\n"); 391 printf("No Memory\n");
392 return; 392 return;
393 } 393 }
394 restart: 394 restart:
395 395
396 /* read the block no allocated to a file */ 396 /* read the block no allocated to a file */
397 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; 397 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
398 direct_blk_idx++) { 398 direct_blk_idx++) {
399 root_blknr = read_allocated_block(g_parent_inode, 399 root_blknr = read_allocated_block(g_parent_inode,
400 direct_blk_idx); 400 direct_blk_idx);
401 if (root_blknr == 0) { 401 if (root_blknr == 0) {
402 first_block_no_of_root = previous_blknr; 402 first_block_no_of_root = previous_blknr;
403 break; 403 break;
404 } 404 }
405 previous_blknr = root_blknr; 405 previous_blknr = root_blknr;
406 } 406 }
407 407
408 status = ext4fs_devread(first_block_no_of_root 408 status = ext4fs_devread((lbaint_t)first_block_no_of_root
409 * fs->sect_perblk, 409 * fs->sect_perblk,
410 0, fs->blksz, root_first_block_buffer); 410 0, fs->blksz, root_first_block_buffer);
411 if (status == 0) 411 if (status == 0)
412 goto fail; 412 goto fail;
413 413
414 if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root)) 414 if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root))
415 goto fail; 415 goto fail;
416 dir = (struct ext2_dirent *)root_first_block_buffer; 416 dir = (struct ext2_dirent *)root_first_block_buffer;
417 totalbytes = 0; 417 totalbytes = 0;
418 while (dir->direntlen > 0) { 418 while (dir->direntlen > 0) {
419 /* 419 /*
420 * blocksize-totalbytes because last directory length 420 * blocksize-totalbytes because last directory length
421 * i.e. dir->direntlen is free availble space in the 421 * i.e. dir->direntlen is free availble space in the
422 * block that means it is a last entry of directory 422 * block that means it is a last entry of directory
423 * entry 423 * entry
424 */ 424 */
425 425
426 /* traversing the each directory entry */ 426 /* traversing the each directory entry */
427 if (fs->blksz - totalbytes == dir->direntlen) { 427 if (fs->blksz - totalbytes == dir->direntlen) {
428 if (strlen(filename) % 4 != 0) 428 if (strlen(filename) % 4 != 0)
429 padding_factor = 4 - (strlen(filename) % 4); 429 padding_factor = 4 - (strlen(filename) % 4);
430 430
431 new_entry_byte_reqd = strlen(filename) + 431 new_entry_byte_reqd = strlen(filename) +
432 sizeof(struct ext2_dirent) + padding_factor; 432 sizeof(struct ext2_dirent) + padding_factor;
433 padding_factor = 0; 433 padding_factor = 0;
434 /* 434 /*
435 * update last directory entry length to its 435 * update last directory entry length to its
436 * length because we are creating new directory 436 * length because we are creating new directory
437 * entry 437 * entry
438 */ 438 */
439 if (dir->namelen % 4 != 0) 439 if (dir->namelen % 4 != 0)
440 padding_factor = 4 - (dir->namelen % 4); 440 padding_factor = 4 - (dir->namelen % 4);
441 441
442 last_entry_dirlen = dir->namelen + 442 last_entry_dirlen = dir->namelen +
443 sizeof(struct ext2_dirent) + padding_factor; 443 sizeof(struct ext2_dirent) + padding_factor;
444 if ((fs->blksz - totalbytes - last_entry_dirlen) < 444 if ((fs->blksz - totalbytes - last_entry_dirlen) <
445 new_entry_byte_reqd) { 445 new_entry_byte_reqd) {
446 printf("1st Block Full:Allocate new block\n"); 446 printf("1st Block Full:Allocate new block\n");
447 447
448 if (direct_blk_idx == INDIRECT_BLOCKS - 1) { 448 if (direct_blk_idx == INDIRECT_BLOCKS - 1) {
449 printf("Directory exceeds limit\n"); 449 printf("Directory exceeds limit\n");
450 goto fail; 450 goto fail;
451 } 451 }
452 g_parent_inode->b.blocks.dir_blocks 452 g_parent_inode->b.blocks.dir_blocks
453 [direct_blk_idx] = ext4fs_get_new_blk_no(); 453 [direct_blk_idx] = ext4fs_get_new_blk_no();
454 if (g_parent_inode->b.blocks.dir_blocks 454 if (g_parent_inode->b.blocks.dir_blocks
455 [direct_blk_idx] == -1) { 455 [direct_blk_idx] == -1) {
456 printf("no block left to assign\n"); 456 printf("no block left to assign\n");
457 goto fail; 457 goto fail;
458 } 458 }
459 put_ext4(((uint64_t) 459 put_ext4(((uint64_t)
460 (g_parent_inode->b. 460 (g_parent_inode->b.
461 blocks.dir_blocks[direct_blk_idx] * 461 blocks.dir_blocks[direct_blk_idx] *
462 fs->blksz)), zero_buffer, fs->blksz); 462 fs->blksz)), zero_buffer, fs->blksz);
463 g_parent_inode->size = 463 g_parent_inode->size =
464 g_parent_inode->size + fs->blksz; 464 g_parent_inode->size + fs->blksz;
465 g_parent_inode->blockcnt = 465 g_parent_inode->blockcnt =
466 g_parent_inode->blockcnt + fs->sect_perblk; 466 g_parent_inode->blockcnt + fs->sect_perblk;
467 if (ext4fs_put_metadata 467 if (ext4fs_put_metadata
468 (root_first_block_buffer, 468 (root_first_block_buffer,
469 first_block_no_of_root)) 469 first_block_no_of_root))
470 goto fail; 470 goto fail;
471 goto restart; 471 goto restart;
472 } 472 }
473 dir->direntlen = last_entry_dirlen; 473 dir->direntlen = last_entry_dirlen;
474 break; 474 break;
475 } 475 }
476 476
477 templength = dir->direntlen; 477 templength = dir->direntlen;
478 totalbytes = totalbytes + templength; 478 totalbytes = totalbytes + templength;
479 sizeof_void_space = check_void_in_dentry(dir, filename); 479 sizeof_void_space = check_void_in_dentry(dir, filename);
480 if (sizeof_void_space) 480 if (sizeof_void_space)
481 break; 481 break;
482 482
483 dir = (struct ext2_dirent *)((char *)dir + templength); 483 dir = (struct ext2_dirent *)((char *)dir + templength);
484 } 484 }
485 485
486 /* make a pointer ready for creating next directory entry */ 486 /* make a pointer ready for creating next directory entry */
487 templength = dir->direntlen; 487 templength = dir->direntlen;
488 totalbytes = totalbytes + templength; 488 totalbytes = totalbytes + templength;
489 dir = (struct ext2_dirent *)((char *)dir + templength); 489 dir = (struct ext2_dirent *)((char *)dir + templength);
490 490
491 /* get the next available inode number */ 491 /* get the next available inode number */
492 inodeno = ext4fs_get_new_inode_no(); 492 inodeno = ext4fs_get_new_inode_no();
493 if (inodeno == -1) { 493 if (inodeno == -1) {
494 printf("no inode left to assign\n"); 494 printf("no inode left to assign\n");
495 goto fail; 495 goto fail;
496 } 496 }
497 dir->inode = inodeno; 497 dir->inode = inodeno;
498 if (sizeof_void_space) 498 if (sizeof_void_space)
499 dir->direntlen = sizeof_void_space; 499 dir->direntlen = sizeof_void_space;
500 else 500 else
501 dir->direntlen = fs->blksz - totalbytes; 501 dir->direntlen = fs->blksz - totalbytes;
502 502
503 dir->namelen = strlen(filename); 503 dir->namelen = strlen(filename);
504 dir->filetype = FILETYPE_REG; /* regular file */ 504 dir->filetype = FILETYPE_REG; /* regular file */
505 temp_dir = (char *)dir; 505 temp_dir = (char *)dir;
506 temp_dir = temp_dir + sizeof(struct ext2_dirent); 506 temp_dir = temp_dir + sizeof(struct ext2_dirent);
507 memcpy(temp_dir, filename, strlen(filename)); 507 memcpy(temp_dir, filename, strlen(filename));
508 508
509 *p_ino = inodeno; 509 *p_ino = inodeno;
510 510
511 /* update or write the 1st block of root inode */ 511 /* update or write the 1st block of root inode */
512 if (ext4fs_put_metadata(root_first_block_buffer, 512 if (ext4fs_put_metadata(root_first_block_buffer,
513 first_block_no_of_root)) 513 first_block_no_of_root))
514 goto fail; 514 goto fail;
515 515
516 fail: 516 fail:
517 free(zero_buffer); 517 free(zero_buffer);
518 free(root_first_block_buffer); 518 free(root_first_block_buffer);
519 } 519 }
520 520
521 static int search_dir(struct ext2_inode *parent_inode, char *dirname) 521 static int search_dir(struct ext2_inode *parent_inode, char *dirname)
522 { 522 {
523 int status; 523 int status;
524 int inodeno; 524 int inodeno;
525 int totalbytes; 525 int totalbytes;
526 int templength; 526 int templength;
527 int direct_blk_idx; 527 int direct_blk_idx;
528 long int blknr; 528 long int blknr;
529 int found = 0; 529 int found = 0;
530 char *ptr = NULL; 530 char *ptr = NULL;
531 unsigned char *block_buffer = NULL; 531 unsigned char *block_buffer = NULL;
532 struct ext2_dirent *dir = NULL; 532 struct ext2_dirent *dir = NULL;
533 struct ext2_dirent *previous_dir = NULL; 533 struct ext2_dirent *previous_dir = NULL;
534 struct ext_filesystem *fs = get_fs(); 534 struct ext_filesystem *fs = get_fs();
535 535
536 /* read the block no allocated to a file */ 536 /* read the block no allocated to a file */
537 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; 537 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
538 direct_blk_idx++) { 538 direct_blk_idx++) {
539 blknr = read_allocated_block(parent_inode, direct_blk_idx); 539 blknr = read_allocated_block(parent_inode, direct_blk_idx);
540 if (blknr == 0) 540 if (blknr == 0)
541 goto fail; 541 goto fail;
542 542
543 /* read the blocks of parenet inode */ 543 /* read the blocks of parenet inode */
544 block_buffer = zalloc(fs->blksz); 544 block_buffer = zalloc(fs->blksz);
545 if (!block_buffer) 545 if (!block_buffer)
546 goto fail; 546 goto fail;
547 547
548 status = ext4fs_devread(blknr * fs->sect_perblk, 548 status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
549 0, fs->blksz, (char *)block_buffer); 549 0, fs->blksz, (char *)block_buffer);
550 if (status == 0) 550 if (status == 0)
551 goto fail; 551 goto fail;
552 552
553 dir = (struct ext2_dirent *)block_buffer; 553 dir = (struct ext2_dirent *)block_buffer;
554 ptr = (char *)dir; 554 ptr = (char *)dir;
555 totalbytes = 0; 555 totalbytes = 0;
556 while (dir->direntlen >= 0) { 556 while (dir->direntlen >= 0) {
557 /* 557 /*
558 * blocksize-totalbytes because last directory 558 * blocksize-totalbytes because last directory
559 * length i.e.,*dir->direntlen is free availble 559 * length i.e.,*dir->direntlen is free availble
560 * space in the block that means 560 * space in the block that means
561 * it is a last entry of directory entry 561 * it is a last entry of directory entry
562 */ 562 */
563 if (strlen(dirname) == dir->namelen) { 563 if (strlen(dirname) == dir->namelen) {
564 if (strncmp(dirname, ptr + 564 if (strncmp(dirname, ptr +
565 sizeof(struct ext2_dirent), 565 sizeof(struct ext2_dirent),
566 dir->namelen) == 0) { 566 dir->namelen) == 0) {
567 previous_dir->direntlen += 567 previous_dir->direntlen +=
568 dir->direntlen; 568 dir->direntlen;
569 inodeno = dir->inode; 569 inodeno = dir->inode;
570 dir->inode = 0; 570 dir->inode = 0;
571 found = 1; 571 found = 1;
572 break; 572 break;
573 } 573 }
574 } 574 }
575 575
576 if (fs->blksz - totalbytes == dir->direntlen) 576 if (fs->blksz - totalbytes == dir->direntlen)
577 break; 577 break;
578 578
579 /* traversing the each directory entry */ 579 /* traversing the each directory entry */
580 templength = dir->direntlen; 580 templength = dir->direntlen;
581 totalbytes = totalbytes + templength; 581 totalbytes = totalbytes + templength;
582 previous_dir = dir; 582 previous_dir = dir;
583 dir = (struct ext2_dirent *)((char *)dir + templength); 583 dir = (struct ext2_dirent *)((char *)dir + templength);
584 ptr = (char *)dir; 584 ptr = (char *)dir;
585 } 585 }
586 586
587 if (found == 1) { 587 if (found == 1) {
588 free(block_buffer); 588 free(block_buffer);
589 block_buffer = NULL; 589 block_buffer = NULL;
590 return inodeno; 590 return inodeno;
591 } 591 }
592 592
593 free(block_buffer); 593 free(block_buffer);
594 block_buffer = NULL; 594 block_buffer = NULL;
595 } 595 }
596 596
597 fail: 597 fail:
598 free(block_buffer); 598 free(block_buffer);
599 599
600 return -1; 600 return -1;
601 } 601 }
602 602
603 static int find_dir_depth(char *dirname) 603 static int find_dir_depth(char *dirname)
604 { 604 {
605 char *token = strtok(dirname, "/"); 605 char *token = strtok(dirname, "/");
606 int count = 0; 606 int count = 0;
607 while (token != NULL) { 607 while (token != NULL) {
608 token = strtok(NULL, "/"); 608 token = strtok(NULL, "/");
609 count++; 609 count++;
610 } 610 }
611 return count + 1 + 1; 611 return count + 1 + 1;
612 /* 612 /*
613 * for example for string /home/temp 613 * for example for string /home/temp
614 * depth=home(1)+temp(1)+1 extra for NULL; 614 * depth=home(1)+temp(1)+1 extra for NULL;
615 * so count is 4; 615 * so count is 4;
616 */ 616 */
617 } 617 }
618 618
619 static int parse_path(char **arr, char *dirname) 619 static int parse_path(char **arr, char *dirname)
620 { 620 {
621 char *token = strtok(dirname, "/"); 621 char *token = strtok(dirname, "/");
622 int i = 0; 622 int i = 0;
623 623
624 /* add root */ 624 /* add root */
625 arr[i] = zalloc(strlen("/") + 1); 625 arr[i] = zalloc(strlen("/") + 1);
626 if (!arr[i]) 626 if (!arr[i])
627 return -ENOMEM; 627 return -ENOMEM;
628 628
629 arr[i++] = "/"; 629 arr[i++] = "/";
630 630
631 /* add each path entry after root */ 631 /* add each path entry after root */
632 while (token != NULL) { 632 while (token != NULL) {
633 arr[i] = zalloc(strlen(token) + 1); 633 arr[i] = zalloc(strlen(token) + 1);
634 if (!arr[i]) 634 if (!arr[i])
635 return -ENOMEM; 635 return -ENOMEM;
636 memcpy(arr[i++], token, strlen(token)); 636 memcpy(arr[i++], token, strlen(token));
637 token = strtok(NULL, "/"); 637 token = strtok(NULL, "/");
638 } 638 }
639 arr[i] = NULL; 639 arr[i] = NULL;
640 640
641 return 0; 641 return 0;
642 } 642 }
643 643
644 int ext4fs_iget(int inode_no, struct ext2_inode *inode) 644 int ext4fs_iget(int inode_no, struct ext2_inode *inode)
645 { 645 {
646 if (ext4fs_read_inode(ext4fs_root, inode_no, inode) == 0) 646 if (ext4fs_read_inode(ext4fs_root, inode_no, inode) == 0)
647 return -1; 647 return -1;
648 648
649 return 0; 649 return 0;
650 } 650 }
651 651
652 /* 652 /*
653 * Function: ext4fs_get_parent_inode_num 653 * Function: ext4fs_get_parent_inode_num
654 * Return Value: inode Number of the parent directory of file/Directory to be 654 * Return Value: inode Number of the parent directory of file/Directory to be
655 * created 655 * created
656 * dirname : Input parmater, input path name of the file/directory to be created 656 * dirname : Input parmater, input path name of the file/directory to be created
657 * dname : Output parameter, to be filled with the name of the directory 657 * dname : Output parameter, to be filled with the name of the directory
658 * extracted from dirname 658 * extracted from dirname
659 */ 659 */
660 int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags) 660 int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags)
661 { 661 {
662 int i; 662 int i;
663 int depth = 0; 663 int depth = 0;
664 int matched_inode_no; 664 int matched_inode_no;
665 int result_inode_no = -1; 665 int result_inode_no = -1;
666 char **ptr = NULL; 666 char **ptr = NULL;
667 char *depth_dirname = NULL; 667 char *depth_dirname = NULL;
668 char *parse_dirname = NULL; 668 char *parse_dirname = NULL;
669 struct ext2_inode *parent_inode = NULL; 669 struct ext2_inode *parent_inode = NULL;
670 struct ext2_inode *first_inode = NULL; 670 struct ext2_inode *first_inode = NULL;
671 struct ext2_inode temp_inode; 671 struct ext2_inode temp_inode;
672 672
673 if (*dirname != '/') { 673 if (*dirname != '/') {
674 printf("Please supply Absolute path\n"); 674 printf("Please supply Absolute path\n");
675 return -1; 675 return -1;
676 } 676 }
677 677
678 /* TODO: input validation make equivalent to linux */ 678 /* TODO: input validation make equivalent to linux */
679 depth_dirname = zalloc(strlen(dirname) + 1); 679 depth_dirname = zalloc(strlen(dirname) + 1);
680 if (!depth_dirname) 680 if (!depth_dirname)
681 return -ENOMEM; 681 return -ENOMEM;
682 682
683 memcpy(depth_dirname, dirname, strlen(dirname)); 683 memcpy(depth_dirname, dirname, strlen(dirname));
684 depth = find_dir_depth(depth_dirname); 684 depth = find_dir_depth(depth_dirname);
685 parse_dirname = zalloc(strlen(dirname) + 1); 685 parse_dirname = zalloc(strlen(dirname) + 1);
686 if (!parse_dirname) 686 if (!parse_dirname)
687 goto fail; 687 goto fail;
688 memcpy(parse_dirname, dirname, strlen(dirname)); 688 memcpy(parse_dirname, dirname, strlen(dirname));
689 689
690 /* allocate memory for each directory level */ 690 /* allocate memory for each directory level */
691 ptr = zalloc((depth) * sizeof(char *)); 691 ptr = zalloc((depth) * sizeof(char *));
692 if (!ptr) 692 if (!ptr)
693 goto fail; 693 goto fail;
694 if (parse_path(ptr, parse_dirname)) 694 if (parse_path(ptr, parse_dirname))
695 goto fail; 695 goto fail;
696 parent_inode = zalloc(sizeof(struct ext2_inode)); 696 parent_inode = zalloc(sizeof(struct ext2_inode));
697 if (!parent_inode) 697 if (!parent_inode)
698 goto fail; 698 goto fail;
699 first_inode = zalloc(sizeof(struct ext2_inode)); 699 first_inode = zalloc(sizeof(struct ext2_inode));
700 if (!first_inode) 700 if (!first_inode)
701 goto fail; 701 goto fail;
702 memcpy(parent_inode, ext4fs_root->inode, sizeof(struct ext2_inode)); 702 memcpy(parent_inode, ext4fs_root->inode, sizeof(struct ext2_inode));
703 memcpy(first_inode, parent_inode, sizeof(struct ext2_inode)); 703 memcpy(first_inode, parent_inode, sizeof(struct ext2_inode));
704 if (flags & F_FILE) 704 if (flags & F_FILE)
705 result_inode_no = EXT2_ROOT_INO; 705 result_inode_no = EXT2_ROOT_INO;
706 for (i = 1; i < depth; i++) { 706 for (i = 1; i < depth; i++) {
707 matched_inode_no = search_dir(parent_inode, ptr[i]); 707 matched_inode_no = search_dir(parent_inode, ptr[i]);
708 if (matched_inode_no == -1) { 708 if (matched_inode_no == -1) {
709 if (ptr[i + 1] == NULL && i == 1) { 709 if (ptr[i + 1] == NULL && i == 1) {
710 result_inode_no = EXT2_ROOT_INO; 710 result_inode_no = EXT2_ROOT_INO;
711 goto end; 711 goto end;
712 } else { 712 } else {
713 if (ptr[i + 1] == NULL) 713 if (ptr[i + 1] == NULL)
714 break; 714 break;
715 printf("Invalid path\n"); 715 printf("Invalid path\n");
716 result_inode_no = -1; 716 result_inode_no = -1;
717 goto fail; 717 goto fail;
718 } 718 }
719 } else { 719 } else {
720 if (ptr[i + 1] != NULL) { 720 if (ptr[i + 1] != NULL) {
721 memset(parent_inode, '\0', 721 memset(parent_inode, '\0',
722 sizeof(struct ext2_inode)); 722 sizeof(struct ext2_inode));
723 if (ext4fs_iget(matched_inode_no, 723 if (ext4fs_iget(matched_inode_no,
724 parent_inode)) { 724 parent_inode)) {
725 result_inode_no = -1; 725 result_inode_no = -1;
726 goto fail; 726 goto fail;
727 } 727 }
728 result_inode_no = matched_inode_no; 728 result_inode_no = matched_inode_no;
729 } else { 729 } else {
730 break; 730 break;
731 } 731 }
732 } 732 }
733 } 733 }
734 734
735 end: 735 end:
736 if (i == 1) 736 if (i == 1)
737 matched_inode_no = search_dir(first_inode, ptr[i]); 737 matched_inode_no = search_dir(first_inode, ptr[i]);
738 else 738 else
739 matched_inode_no = search_dir(parent_inode, ptr[i]); 739 matched_inode_no = search_dir(parent_inode, ptr[i]);
740 740
741 if (matched_inode_no != -1) { 741 if (matched_inode_no != -1) {
742 ext4fs_iget(matched_inode_no, &temp_inode); 742 ext4fs_iget(matched_inode_no, &temp_inode);
743 if (temp_inode.mode & S_IFDIR) { 743 if (temp_inode.mode & S_IFDIR) {
744 printf("It is a Directory\n"); 744 printf("It is a Directory\n");
745 result_inode_no = -1; 745 result_inode_no = -1;
746 goto fail; 746 goto fail;
747 } 747 }
748 } 748 }
749 749
750 if (strlen(ptr[i]) > 256) { 750 if (strlen(ptr[i]) > 256) {
751 result_inode_no = -1; 751 result_inode_no = -1;
752 goto fail; 752 goto fail;
753 } 753 }
754 memcpy(dname, ptr[i], strlen(ptr[i])); 754 memcpy(dname, ptr[i], strlen(ptr[i]));
755 755
756 fail: 756 fail:
757 free(depth_dirname); 757 free(depth_dirname);
758 free(parse_dirname); 758 free(parse_dirname);
759 free(ptr); 759 free(ptr);
760 free(parent_inode); 760 free(parent_inode);
761 free(first_inode); 761 free(first_inode);
762 762
763 return result_inode_no; 763 return result_inode_no;
764 } 764 }
765 765
766 static int check_filename(char *filename, unsigned int blknr) 766 static int check_filename(char *filename, unsigned int blknr)
767 { 767 {
768 unsigned int first_block_no_of_root; 768 unsigned int first_block_no_of_root;
769 int totalbytes = 0; 769 int totalbytes = 0;
770 int templength = 0; 770 int templength = 0;
771 int status, inodeno; 771 int status, inodeno;
772 int found = 0; 772 int found = 0;
773 char *root_first_block_buffer = NULL; 773 char *root_first_block_buffer = NULL;
774 char *root_first_block_addr = NULL; 774 char *root_first_block_addr = NULL;
775 struct ext2_dirent *dir = NULL; 775 struct ext2_dirent *dir = NULL;
776 struct ext2_dirent *previous_dir = NULL; 776 struct ext2_dirent *previous_dir = NULL;
777 char *ptr = NULL; 777 char *ptr = NULL;
778 struct ext_filesystem *fs = get_fs(); 778 struct ext_filesystem *fs = get_fs();
779 779
780 /* get the first block of root */ 780 /* get the first block of root */
781 first_block_no_of_root = blknr; 781 first_block_no_of_root = blknr;
782 root_first_block_buffer = zalloc(fs->blksz); 782 root_first_block_buffer = zalloc(fs->blksz);
783 if (!root_first_block_buffer) 783 if (!root_first_block_buffer)
784 return -ENOMEM; 784 return -ENOMEM;
785 root_first_block_addr = root_first_block_buffer; 785 root_first_block_addr = root_first_block_buffer;
786 status = ext4fs_devread(first_block_no_of_root * 786 status = ext4fs_devread((lbaint_t)first_block_no_of_root *
787 fs->sect_perblk, 0, 787 fs->sect_perblk, 0,
788 fs->blksz, root_first_block_buffer); 788 fs->blksz, root_first_block_buffer);
789 if (status == 0) 789 if (status == 0)
790 goto fail; 790 goto fail;
791 791
792 if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root)) 792 if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root))
793 goto fail; 793 goto fail;
794 dir = (struct ext2_dirent *)root_first_block_buffer; 794 dir = (struct ext2_dirent *)root_first_block_buffer;
795 ptr = (char *)dir; 795 ptr = (char *)dir;
796 totalbytes = 0; 796 totalbytes = 0;
797 while (dir->direntlen >= 0) { 797 while (dir->direntlen >= 0) {
798 /* 798 /*
799 * blocksize-totalbytes because last 799 * blocksize-totalbytes because last
800 * directory length i.e., *dir->direntlen 800 * directory length i.e., *dir->direntlen
801 * is free availble space in the block that 801 * is free availble space in the block that
802 * means it is a last entry of directory entry 802 * means it is a last entry of directory entry
803 */ 803 */
804 if (strlen(filename) == dir->namelen) { 804 if (strlen(filename) == dir->namelen) {
805 if (strncmp(filename, ptr + sizeof(struct ext2_dirent), 805 if (strncmp(filename, ptr + sizeof(struct ext2_dirent),
806 dir->namelen) == 0) { 806 dir->namelen) == 0) {
807 printf("file found deleting\n"); 807 printf("file found deleting\n");
808 previous_dir->direntlen += dir->direntlen; 808 previous_dir->direntlen += dir->direntlen;
809 inodeno = dir->inode; 809 inodeno = dir->inode;
810 dir->inode = 0; 810 dir->inode = 0;
811 found = 1; 811 found = 1;
812 break; 812 break;
813 } 813 }
814 } 814 }
815 815
816 if (fs->blksz - totalbytes == dir->direntlen) 816 if (fs->blksz - totalbytes == dir->direntlen)
817 break; 817 break;
818 818
819 /* traversing the each directory entry */ 819 /* traversing the each directory entry */
820 templength = dir->direntlen; 820 templength = dir->direntlen;
821 totalbytes = totalbytes + templength; 821 totalbytes = totalbytes + templength;
822 previous_dir = dir; 822 previous_dir = dir;
823 dir = (struct ext2_dirent *)((char *)dir + templength); 823 dir = (struct ext2_dirent *)((char *)dir + templength);
824 ptr = (char *)dir; 824 ptr = (char *)dir;
825 } 825 }
826 826
827 827
828 if (found == 1) { 828 if (found == 1) {
829 if (ext4fs_put_metadata(root_first_block_addr, 829 if (ext4fs_put_metadata(root_first_block_addr,
830 first_block_no_of_root)) 830 first_block_no_of_root))
831 goto fail; 831 goto fail;
832 return inodeno; 832 return inodeno;
833 } 833 }
834 fail: 834 fail:
835 free(root_first_block_buffer); 835 free(root_first_block_buffer);
836 836
837 return -1; 837 return -1;
838 } 838 }
839 839
840 int ext4fs_filename_check(char *filename) 840 int ext4fs_filename_check(char *filename)
841 { 841 {
842 short direct_blk_idx = 0; 842 short direct_blk_idx = 0;
843 long int blknr = -1; 843 long int blknr = -1;
844 int inodeno = -1; 844 int inodeno = -1;
845 845
846 /* read the block no allocated to a file */ 846 /* read the block no allocated to a file */
847 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; 847 for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
848 direct_blk_idx++) { 848 direct_blk_idx++) {
849 blknr = read_allocated_block(g_parent_inode, direct_blk_idx); 849 blknr = read_allocated_block(g_parent_inode, direct_blk_idx);
850 if (blknr == 0) 850 if (blknr == 0)
851 break; 851 break;
852 inodeno = check_filename(filename, blknr); 852 inodeno = check_filename(filename, blknr);
853 if (inodeno != -1) 853 if (inodeno != -1)
854 return inodeno; 854 return inodeno;
855 } 855 }
856 856
857 return -1; 857 return -1;
858 } 858 }
859 859
860 long int ext4fs_get_new_blk_no(void) 860 long int ext4fs_get_new_blk_no(void)
861 { 861 {
862 short i; 862 short i;
863 short status; 863 short status;
864 int remainder; 864 int remainder;
865 unsigned int bg_idx; 865 unsigned int bg_idx;
866 static int prev_bg_bitmap_index = -1; 866 static int prev_bg_bitmap_index = -1;
867 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 867 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
868 struct ext_filesystem *fs = get_fs(); 868 struct ext_filesystem *fs = get_fs();
869 char *journal_buffer = zalloc(fs->blksz); 869 char *journal_buffer = zalloc(fs->blksz);
870 char *zero_buffer = zalloc(fs->blksz); 870 char *zero_buffer = zalloc(fs->blksz);
871 if (!journal_buffer || !zero_buffer) 871 if (!journal_buffer || !zero_buffer)
872 goto fail; 872 goto fail;
873 struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; 873 struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable;
874 874
875 if (fs->first_pass_bbmap == 0) { 875 if (fs->first_pass_bbmap == 0) {
876 for (i = 0; i < fs->no_blkgrp; i++) { 876 for (i = 0; i < fs->no_blkgrp; i++) {
877 if (bgd[i].free_blocks) { 877 if (bgd[i].free_blocks) {
878 if (bgd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) { 878 if (bgd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) {
879 put_ext4(((uint64_t) (bgd[i].block_id * 879 put_ext4(((uint64_t) (bgd[i].block_id *
880 fs->blksz)), 880 fs->blksz)),
881 zero_buffer, fs->blksz); 881 zero_buffer, fs->blksz);
882 bgd[i].bg_flags = 882 bgd[i].bg_flags =
883 bgd[i]. 883 bgd[i].
884 bg_flags & ~EXT4_BG_BLOCK_UNINIT; 884 bg_flags & ~EXT4_BG_BLOCK_UNINIT;
885 memcpy(fs->blk_bmaps[i], zero_buffer, 885 memcpy(fs->blk_bmaps[i], zero_buffer,
886 fs->blksz); 886 fs->blksz);
887 } 887 }
888 fs->curr_blkno = 888 fs->curr_blkno =
889 _get_new_blk_no(fs->blk_bmaps[i]); 889 _get_new_blk_no(fs->blk_bmaps[i]);
890 if (fs->curr_blkno == -1) 890 if (fs->curr_blkno == -1)
891 /* if block bitmap is completely fill */ 891 /* if block bitmap is completely fill */
892 continue; 892 continue;
893 fs->curr_blkno = fs->curr_blkno + 893 fs->curr_blkno = fs->curr_blkno +
894 (i * fs->blksz * 8); 894 (i * fs->blksz * 8);
895 fs->first_pass_bbmap++; 895 fs->first_pass_bbmap++;
896 bgd[i].free_blocks--; 896 bgd[i].free_blocks--;
897 fs->sb->free_blocks--; 897 fs->sb->free_blocks--;
898 status = ext4fs_devread(bgd[i].block_id * 898 status = ext4fs_devread((lbaint_t)
899 bgd[i].block_id *
899 fs->sect_perblk, 0, 900 fs->sect_perblk, 0,
900 fs->blksz, 901 fs->blksz,
901 journal_buffer); 902 journal_buffer);
902 if (status == 0) 903 if (status == 0)
903 goto fail; 904 goto fail;
904 if (ext4fs_log_journal(journal_buffer, 905 if (ext4fs_log_journal(journal_buffer,
905 bgd[i].block_id)) 906 bgd[i].block_id))
906 goto fail; 907 goto fail;
907 goto success; 908 goto success;
908 } else { 909 } else {
909 debug("no space left on block group %d\n", i); 910 debug("no space left on block group %d\n", i);
910 } 911 }
911 } 912 }
912 913
913 goto fail; 914 goto fail;
914 } else { 915 } else {
915 restart: 916 restart:
916 fs->curr_blkno++; 917 fs->curr_blkno++;
917 /* get the blockbitmap index respective to blockno */ 918 /* get the blockbitmap index respective to blockno */
918 if (fs->blksz != 1024) { 919 if (fs->blksz != 1024) {
919 bg_idx = fs->curr_blkno / blk_per_grp; 920 bg_idx = fs->curr_blkno / blk_per_grp;
920 } else { 921 } else {
921 bg_idx = fs->curr_blkno / blk_per_grp; 922 bg_idx = fs->curr_blkno / blk_per_grp;
922 remainder = fs->curr_blkno % blk_per_grp; 923 remainder = fs->curr_blkno % blk_per_grp;
923 if (!remainder) 924 if (!remainder)
924 bg_idx--; 925 bg_idx--;
925 } 926 }
926 927
927 /* 928 /*
928 * To skip completely filled block group bitmaps 929 * To skip completely filled block group bitmaps
929 * Optimize the block allocation 930 * Optimize the block allocation
930 */ 931 */
931 if (bg_idx >= fs->no_blkgrp) 932 if (bg_idx >= fs->no_blkgrp)
932 goto fail; 933 goto fail;
933 934
934 if (bgd[bg_idx].free_blocks == 0) { 935 if (bgd[bg_idx].free_blocks == 0) {
935 debug("block group %u is full. Skipping\n", bg_idx); 936 debug("block group %u is full. Skipping\n", bg_idx);
936 fs->curr_blkno = fs->curr_blkno + blk_per_grp; 937 fs->curr_blkno = fs->curr_blkno + blk_per_grp;
937 fs->curr_blkno--; 938 fs->curr_blkno--;
938 goto restart; 939 goto restart;
939 } 940 }
940 941
941 if (bgd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) { 942 if (bgd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) {
942 memset(zero_buffer, '\0', fs->blksz); 943 memset(zero_buffer, '\0', fs->blksz);
943 put_ext4(((uint64_t) (bgd[bg_idx].block_id * 944 put_ext4(((uint64_t) (bgd[bg_idx].block_id *
944 fs->blksz)), zero_buffer, fs->blksz); 945 fs->blksz)), zero_buffer, fs->blksz);
945 memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz); 946 memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz);
946 bgd[bg_idx].bg_flags = bgd[bg_idx].bg_flags & 947 bgd[bg_idx].bg_flags = bgd[bg_idx].bg_flags &
947 ~EXT4_BG_BLOCK_UNINIT; 948 ~EXT4_BG_BLOCK_UNINIT;
948 } 949 }
949 950
950 if (ext4fs_set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx], 951 if (ext4fs_set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx],
951 bg_idx) != 0) { 952 bg_idx) != 0) {
952 debug("going for restart for the block no %ld %u\n", 953 debug("going for restart for the block no %ld %u\n",
953 fs->curr_blkno, bg_idx); 954 fs->curr_blkno, bg_idx);
954 goto restart; 955 goto restart;
955 } 956 }
956 957
957 /* journal backup */ 958 /* journal backup */
958 if (prev_bg_bitmap_index != bg_idx) { 959 if (prev_bg_bitmap_index != bg_idx) {
959 memset(journal_buffer, '\0', fs->blksz); 960 memset(journal_buffer, '\0', fs->blksz);
960 status = ext4fs_devread(bgd[bg_idx].block_id 961 status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id
961 * fs->sect_perblk, 962 * fs->sect_perblk,
962 0, fs->blksz, journal_buffer); 963 0, fs->blksz, journal_buffer);
963 if (status == 0) 964 if (status == 0)
964 goto fail; 965 goto fail;
965 if (ext4fs_log_journal(journal_buffer, 966 if (ext4fs_log_journal(journal_buffer,
966 bgd[bg_idx].block_id)) 967 bgd[bg_idx].block_id))
967 goto fail; 968 goto fail;
968 969
969 prev_bg_bitmap_index = bg_idx; 970 prev_bg_bitmap_index = bg_idx;
970 } 971 }
971 bgd[bg_idx].free_blocks--; 972 bgd[bg_idx].free_blocks--;
972 fs->sb->free_blocks--; 973 fs->sb->free_blocks--;
973 goto success; 974 goto success;
974 } 975 }
975 success: 976 success:
976 free(journal_buffer); 977 free(journal_buffer);
977 free(zero_buffer); 978 free(zero_buffer);
978 979
979 return fs->curr_blkno; 980 return fs->curr_blkno;
980 fail: 981 fail:
981 free(journal_buffer); 982 free(journal_buffer);
982 free(zero_buffer); 983 free(zero_buffer);
983 984
984 return -1; 985 return -1;
985 } 986 }
986 987
987 int ext4fs_get_new_inode_no(void) 988 int ext4fs_get_new_inode_no(void)
988 { 989 {
989 short i; 990 short i;
990 short status; 991 short status;
991 unsigned int ibmap_idx; 992 unsigned int ibmap_idx;
992 static int prev_inode_bitmap_index = -1; 993 static int prev_inode_bitmap_index = -1;
993 unsigned int inodes_per_grp = ext4fs_root->sblock.inodes_per_group; 994 unsigned int inodes_per_grp = ext4fs_root->sblock.inodes_per_group;
994 struct ext_filesystem *fs = get_fs(); 995 struct ext_filesystem *fs = get_fs();
995 char *journal_buffer = zalloc(fs->blksz); 996 char *journal_buffer = zalloc(fs->blksz);
996 char *zero_buffer = zalloc(fs->blksz); 997 char *zero_buffer = zalloc(fs->blksz);
997 if (!journal_buffer || !zero_buffer) 998 if (!journal_buffer || !zero_buffer)
998 goto fail; 999 goto fail;
999 struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; 1000 struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable;
1000 1001
1001 if (fs->first_pass_ibmap == 0) { 1002 if (fs->first_pass_ibmap == 0) {
1002 for (i = 0; i < fs->no_blkgrp; i++) { 1003 for (i = 0; i < fs->no_blkgrp; i++) {
1003 if (bgd[i].free_inodes) { 1004 if (bgd[i].free_inodes) {
1004 if (bgd[i].bg_itable_unused != 1005 if (bgd[i].bg_itable_unused !=
1005 bgd[i].free_inodes) 1006 bgd[i].free_inodes)
1006 bgd[i].bg_itable_unused = 1007 bgd[i].bg_itable_unused =
1007 bgd[i].free_inodes; 1008 bgd[i].free_inodes;
1008 if (bgd[i].bg_flags & EXT4_BG_INODE_UNINIT) { 1009 if (bgd[i].bg_flags & EXT4_BG_INODE_UNINIT) {
1009 put_ext4(((uint64_t) 1010 put_ext4(((uint64_t)
1010 (bgd[i].inode_id * 1011 (bgd[i].inode_id *
1011 fs->blksz)), 1012 fs->blksz)),
1012 zero_buffer, fs->blksz); 1013 zero_buffer, fs->blksz);
1013 bgd[i].bg_flags = bgd[i].bg_flags & 1014 bgd[i].bg_flags = bgd[i].bg_flags &
1014 ~EXT4_BG_INODE_UNINIT; 1015 ~EXT4_BG_INODE_UNINIT;
1015 memcpy(fs->inode_bmaps[i], 1016 memcpy(fs->inode_bmaps[i],
1016 zero_buffer, fs->blksz); 1017 zero_buffer, fs->blksz);
1017 } 1018 }
1018 fs->curr_inode_no = 1019 fs->curr_inode_no =
1019 _get_new_inode_no(fs->inode_bmaps[i]); 1020 _get_new_inode_no(fs->inode_bmaps[i]);
1020 if (fs->curr_inode_no == -1) 1021 if (fs->curr_inode_no == -1)
1021 /* if block bitmap is completely fill */ 1022 /* if block bitmap is completely fill */
1022 continue; 1023 continue;
1023 fs->curr_inode_no = fs->curr_inode_no + 1024 fs->curr_inode_no = fs->curr_inode_no +
1024 (i * inodes_per_grp); 1025 (i * inodes_per_grp);
1025 fs->first_pass_ibmap++; 1026 fs->first_pass_ibmap++;
1026 bgd[i].free_inodes--; 1027 bgd[i].free_inodes--;
1027 bgd[i].bg_itable_unused--; 1028 bgd[i].bg_itable_unused--;
1028 fs->sb->free_inodes--; 1029 fs->sb->free_inodes--;
1029 status = ext4fs_devread(bgd[i].inode_id * 1030 status = ext4fs_devread((lbaint_t)
1031 bgd[i].inode_id *
1030 fs->sect_perblk, 0, 1032 fs->sect_perblk, 0,
1031 fs->blksz, 1033 fs->blksz,
1032 journal_buffer); 1034 journal_buffer);
1033 if (status == 0) 1035 if (status == 0)
1034 goto fail; 1036 goto fail;
1035 if (ext4fs_log_journal(journal_buffer, 1037 if (ext4fs_log_journal(journal_buffer,
1036 bgd[i].inode_id)) 1038 bgd[i].inode_id))
1037 goto fail; 1039 goto fail;
1038 goto success; 1040 goto success;
1039 } else 1041 } else
1040 debug("no inode left on block group %d\n", i); 1042 debug("no inode left on block group %d\n", i);
1041 } 1043 }
1042 goto fail; 1044 goto fail;
1043 } else { 1045 } else {
1044 restart: 1046 restart:
1045 fs->curr_inode_no++; 1047 fs->curr_inode_no++;
1046 /* get the blockbitmap index respective to blockno */ 1048 /* get the blockbitmap index respective to blockno */
1047 ibmap_idx = fs->curr_inode_no / inodes_per_grp; 1049 ibmap_idx = fs->curr_inode_no / inodes_per_grp;
1048 if (bgd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) { 1050 if (bgd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) {
1049 memset(zero_buffer, '\0', fs->blksz); 1051 memset(zero_buffer, '\0', fs->blksz);
1050 put_ext4(((uint64_t) (bgd[ibmap_idx].inode_id * 1052 put_ext4(((uint64_t) (bgd[ibmap_idx].inode_id *
1051 fs->blksz)), zero_buffer, 1053 fs->blksz)), zero_buffer,
1052 fs->blksz); 1054 fs->blksz);
1053 bgd[ibmap_idx].bg_flags = 1055 bgd[ibmap_idx].bg_flags =
1054 bgd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT; 1056 bgd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT;
1055 memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer, 1057 memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer,
1056 fs->blksz); 1058 fs->blksz);
1057 } 1059 }
1058 1060
1059 if (ext4fs_set_inode_bmap(fs->curr_inode_no, 1061 if (ext4fs_set_inode_bmap(fs->curr_inode_no,
1060 fs->inode_bmaps[ibmap_idx], 1062 fs->inode_bmaps[ibmap_idx],
1061 ibmap_idx) != 0) { 1063 ibmap_idx) != 0) {
1062 debug("going for restart for the block no %d %u\n", 1064 debug("going for restart for the block no %d %u\n",
1063 fs->curr_inode_no, ibmap_idx); 1065 fs->curr_inode_no, ibmap_idx);
1064 goto restart; 1066 goto restart;
1065 } 1067 }
1066 1068
1067 /* journal backup */ 1069 /* journal backup */
1068 if (prev_inode_bitmap_index != ibmap_idx) { 1070 if (prev_inode_bitmap_index != ibmap_idx) {
1069 memset(journal_buffer, '\0', fs->blksz); 1071 memset(journal_buffer, '\0', fs->blksz);
1070 status = ext4fs_devread(bgd[ibmap_idx].inode_id 1072 status = ext4fs_devread((lbaint_t)
1073 bgd[ibmap_idx].inode_id
1071 * fs->sect_perblk, 1074 * fs->sect_perblk,
1072 0, fs->blksz, journal_buffer); 1075 0, fs->blksz, journal_buffer);
1073 if (status == 0) 1076 if (status == 0)
1074 goto fail; 1077 goto fail;
1075 if (ext4fs_log_journal(journal_buffer, 1078 if (ext4fs_log_journal(journal_buffer,
1076 bgd[ibmap_idx].inode_id)) 1079 bgd[ibmap_idx].inode_id))
1077 goto fail; 1080 goto fail;
1078 prev_inode_bitmap_index = ibmap_idx; 1081 prev_inode_bitmap_index = ibmap_idx;
1079 } 1082 }
1080 if (bgd[ibmap_idx].bg_itable_unused != 1083 if (bgd[ibmap_idx].bg_itable_unused !=
1081 bgd[ibmap_idx].free_inodes) 1084 bgd[ibmap_idx].free_inodes)
1082 bgd[ibmap_idx].bg_itable_unused = 1085 bgd[ibmap_idx].bg_itable_unused =
1083 bgd[ibmap_idx].free_inodes; 1086 bgd[ibmap_idx].free_inodes;
1084 bgd[ibmap_idx].free_inodes--; 1087 bgd[ibmap_idx].free_inodes--;
1085 bgd[ibmap_idx].bg_itable_unused--; 1088 bgd[ibmap_idx].bg_itable_unused--;
1086 fs->sb->free_inodes--; 1089 fs->sb->free_inodes--;
1087 goto success; 1090 goto success;
1088 } 1091 }
1089 1092
1090 success: 1093 success:
1091 free(journal_buffer); 1094 free(journal_buffer);
1092 free(zero_buffer); 1095 free(zero_buffer);
1093 1096
1094 return fs->curr_inode_no; 1097 return fs->curr_inode_no;
1095 fail: 1098 fail:
1096 free(journal_buffer); 1099 free(journal_buffer);
1097 free(zero_buffer); 1100 free(zero_buffer);
1098 1101
1099 return -1; 1102 return -1;
1100 1103
1101 } 1104 }
1102 1105
1103 1106
1104 static void alloc_single_indirect_block(struct ext2_inode *file_inode, 1107 static void alloc_single_indirect_block(struct ext2_inode *file_inode,
1105 unsigned int *total_remaining_blocks, 1108 unsigned int *total_remaining_blocks,
1106 unsigned int *no_blks_reqd) 1109 unsigned int *no_blks_reqd)
1107 { 1110 {
1108 short i; 1111 short i;
1109 short status; 1112 short status;
1110 long int actual_block_no; 1113 long int actual_block_no;
1111 long int si_blockno; 1114 long int si_blockno;
1112 /* si :single indirect */ 1115 /* si :single indirect */
1113 unsigned int *si_buffer = NULL; 1116 unsigned int *si_buffer = NULL;
1114 unsigned int *si_start_addr = NULL; 1117 unsigned int *si_start_addr = NULL;
1115 struct ext_filesystem *fs = get_fs(); 1118 struct ext_filesystem *fs = get_fs();
1116 1119
1117 if (*total_remaining_blocks != 0) { 1120 if (*total_remaining_blocks != 0) {
1118 si_buffer = zalloc(fs->blksz); 1121 si_buffer = zalloc(fs->blksz);
1119 if (!si_buffer) { 1122 if (!si_buffer) {
1120 printf("No Memory\n"); 1123 printf("No Memory\n");
1121 return; 1124 return;
1122 } 1125 }
1123 si_start_addr = si_buffer; 1126 si_start_addr = si_buffer;
1124 si_blockno = ext4fs_get_new_blk_no(); 1127 si_blockno = ext4fs_get_new_blk_no();
1125 if (si_blockno == -1) { 1128 if (si_blockno == -1) {
1126 printf("no block left to assign\n"); 1129 printf("no block left to assign\n");
1127 goto fail; 1130 goto fail;
1128 } 1131 }
1129 (*no_blks_reqd)++; 1132 (*no_blks_reqd)++;
1130 debug("SIPB %ld: %u\n", si_blockno, *total_remaining_blocks); 1133 debug("SIPB %ld: %u\n", si_blockno, *total_remaining_blocks);
1131 1134
1132 status = ext4fs_devread(si_blockno * fs->sect_perblk, 1135 status = ext4fs_devread((lbaint_t)si_blockno * fs->sect_perblk,
1133 0, fs->blksz, (char *)si_buffer); 1136 0, fs->blksz, (char *)si_buffer);
1134 memset(si_buffer, '\0', fs->blksz); 1137 memset(si_buffer, '\0', fs->blksz);
1135 if (status == 0) 1138 if (status == 0)
1136 goto fail; 1139 goto fail;
1137 1140
1138 for (i = 0; i < (fs->blksz / sizeof(int)); i++) { 1141 for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
1139 actual_block_no = ext4fs_get_new_blk_no(); 1142 actual_block_no = ext4fs_get_new_blk_no();
1140 if (actual_block_no == -1) { 1143 if (actual_block_no == -1) {
1141 printf("no block left to assign\n"); 1144 printf("no block left to assign\n");
1142 goto fail; 1145 goto fail;
1143 } 1146 }
1144 *si_buffer = actual_block_no; 1147 *si_buffer = actual_block_no;
1145 debug("SIAB %u: %u\n", *si_buffer, 1148 debug("SIAB %u: %u\n", *si_buffer,
1146 *total_remaining_blocks); 1149 *total_remaining_blocks);
1147 1150
1148 si_buffer++; 1151 si_buffer++;
1149 (*total_remaining_blocks)--; 1152 (*total_remaining_blocks)--;
1150 if (*total_remaining_blocks == 0) 1153 if (*total_remaining_blocks == 0)
1151 break; 1154 break;
1152 } 1155 }
1153 1156
1154 /* write the block to disk */ 1157 /* write the block to disk */
1155 put_ext4(((uint64_t) (si_blockno * fs->blksz)), 1158 put_ext4(((uint64_t) (si_blockno * fs->blksz)),
1156 si_start_addr, fs->blksz); 1159 si_start_addr, fs->blksz);
1157 file_inode->b.blocks.indir_block = si_blockno; 1160 file_inode->b.blocks.indir_block = si_blockno;
1158 } 1161 }
1159 fail: 1162 fail:
1160 free(si_start_addr); 1163 free(si_start_addr);
1161 } 1164 }
1162 1165
1163 static void alloc_double_indirect_block(struct ext2_inode *file_inode, 1166 static void alloc_double_indirect_block(struct ext2_inode *file_inode,
1164 unsigned int *total_remaining_blocks, 1167 unsigned int *total_remaining_blocks,
1165 unsigned int *no_blks_reqd) 1168 unsigned int *no_blks_reqd)
1166 { 1169 {
1167 short i; 1170 short i;
1168 short j; 1171 short j;
1169 short status; 1172 short status;
1170 long int actual_block_no; 1173 long int actual_block_no;
1171 /* di:double indirect */ 1174 /* di:double indirect */
1172 long int di_blockno_parent; 1175 long int di_blockno_parent;
1173 long int di_blockno_child; 1176 long int di_blockno_child;
1174 unsigned int *di_parent_buffer = NULL; 1177 unsigned int *di_parent_buffer = NULL;
1175 unsigned int *di_child_buff = NULL; 1178 unsigned int *di_child_buff = NULL;
1176 unsigned int *di_block_start_addr = NULL; 1179 unsigned int *di_block_start_addr = NULL;
1177 unsigned int *di_child_buff_start = NULL; 1180 unsigned int *di_child_buff_start = NULL;
1178 struct ext_filesystem *fs = get_fs(); 1181 struct ext_filesystem *fs = get_fs();
1179 1182
1180 if (*total_remaining_blocks != 0) { 1183 if (*total_remaining_blocks != 0) {
1181 /* double indirect parent block connecting to inode */ 1184 /* double indirect parent block connecting to inode */
1182 di_blockno_parent = ext4fs_get_new_blk_no(); 1185 di_blockno_parent = ext4fs_get_new_blk_no();
1183 if (di_blockno_parent == -1) { 1186 if (di_blockno_parent == -1) {
1184 printf("no block left to assign\n"); 1187 printf("no block left to assign\n");
1185 goto fail; 1188 goto fail;
1186 } 1189 }
1187 di_parent_buffer = zalloc(fs->blksz); 1190 di_parent_buffer = zalloc(fs->blksz);
1188 if (!di_parent_buffer) 1191 if (!di_parent_buffer)
1189 goto fail; 1192 goto fail;
1190 1193
1191 di_block_start_addr = di_parent_buffer; 1194 di_block_start_addr = di_parent_buffer;
1192 (*no_blks_reqd)++; 1195 (*no_blks_reqd)++;
1193 debug("DIPB %ld: %u\n", di_blockno_parent, 1196 debug("DIPB %ld: %u\n", di_blockno_parent,
1194 *total_remaining_blocks); 1197 *total_remaining_blocks);
1195 1198
1196 status = ext4fs_devread(di_blockno_parent * 1199 status = ext4fs_devread((lbaint_t)di_blockno_parent *
1197 fs->sect_perblk, 0, 1200 fs->sect_perblk, 0,
1198 fs->blksz, (char *)di_parent_buffer); 1201 fs->blksz, (char *)di_parent_buffer);
1199 1202
1200 if (!status) { 1203 if (!status) {
1201 printf("%s: Device read error!\n", __func__); 1204 printf("%s: Device read error!\n", __func__);
1202 goto fail; 1205 goto fail;
1203 } 1206 }
1204 memset(di_parent_buffer, '\0', fs->blksz); 1207 memset(di_parent_buffer, '\0', fs->blksz);
1205 1208
1206 /* 1209 /*
1207 * start:for each double indirect parent 1210 * start:for each double indirect parent
1208 * block create one more block 1211 * block create one more block
1209 */ 1212 */
1210 for (i = 0; i < (fs->blksz / sizeof(int)); i++) { 1213 for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
1211 di_blockno_child = ext4fs_get_new_blk_no(); 1214 di_blockno_child = ext4fs_get_new_blk_no();
1212 if (di_blockno_child == -1) { 1215 if (di_blockno_child == -1) {
1213 printf("no block left to assign\n"); 1216 printf("no block left to assign\n");
1214 goto fail; 1217 goto fail;
1215 } 1218 }
1216 di_child_buff = zalloc(fs->blksz); 1219 di_child_buff = zalloc(fs->blksz);
1217 if (!di_child_buff) 1220 if (!di_child_buff)
1218 goto fail; 1221 goto fail;
1219 1222
1220 di_child_buff_start = di_child_buff; 1223 di_child_buff_start = di_child_buff;
1221 *di_parent_buffer = di_blockno_child; 1224 *di_parent_buffer = di_blockno_child;
1222 di_parent_buffer++; 1225 di_parent_buffer++;
1223 (*no_blks_reqd)++; 1226 (*no_blks_reqd)++;
1224 debug("DICB %ld: %u\n", di_blockno_child, 1227 debug("DICB %ld: %u\n", di_blockno_child,
1225 *total_remaining_blocks); 1228 *total_remaining_blocks);
1226 1229
1227 status = ext4fs_devread(di_blockno_child * 1230 status = ext4fs_devread((lbaint_t)di_blockno_child *
1228 fs->sect_perblk, 0, 1231 fs->sect_perblk, 0,
1229 fs->blksz, 1232 fs->blksz,
1230 (char *)di_child_buff); 1233 (char *)di_child_buff);
1231 1234
1232 if (!status) { 1235 if (!status) {
1233 printf("%s: Device read error!\n", __func__); 1236 printf("%s: Device read error!\n", __func__);
1234 goto fail; 1237 goto fail;
1235 } 1238 }
1236 memset(di_child_buff, '\0', fs->blksz); 1239 memset(di_child_buff, '\0', fs->blksz);
1237 /* filling of actual datablocks for each child */ 1240 /* filling of actual datablocks for each child */
1238 for (j = 0; j < (fs->blksz / sizeof(int)); j++) { 1241 for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
1239 actual_block_no = ext4fs_get_new_blk_no(); 1242 actual_block_no = ext4fs_get_new_blk_no();
1240 if (actual_block_no == -1) { 1243 if (actual_block_no == -1) {
1241 printf("no block left to assign\n"); 1244 printf("no block left to assign\n");
1242 goto fail; 1245 goto fail;
1243 } 1246 }
1244 *di_child_buff = actual_block_no; 1247 *di_child_buff = actual_block_no;
1245 debug("DIAB %ld: %u\n", actual_block_no, 1248 debug("DIAB %ld: %u\n", actual_block_no,
1246 *total_remaining_blocks); 1249 *total_remaining_blocks);
1247 1250
1248 di_child_buff++; 1251 di_child_buff++;
1249 (*total_remaining_blocks)--; 1252 (*total_remaining_blocks)--;
1250 if (*total_remaining_blocks == 0) 1253 if (*total_remaining_blocks == 0)
1251 break; 1254 break;
1252 } 1255 }
1253 /* write the block table */ 1256 /* write the block table */
1254 put_ext4(((uint64_t) (di_blockno_child * fs->blksz)), 1257 put_ext4(((uint64_t) (di_blockno_child * fs->blksz)),
1255 di_child_buff_start, fs->blksz); 1258 di_child_buff_start, fs->blksz);
1256 free(di_child_buff_start); 1259 free(di_child_buff_start);
1257 di_child_buff_start = NULL; 1260 di_child_buff_start = NULL;
1258 1261
1259 if (*total_remaining_blocks == 0) 1262 if (*total_remaining_blocks == 0)
1260 break; 1263 break;
1261 } 1264 }
1262 put_ext4(((uint64_t) (di_blockno_parent * fs->blksz)), 1265 put_ext4(((uint64_t) (di_blockno_parent * fs->blksz)),
1263 di_block_start_addr, fs->blksz); 1266 di_block_start_addr, fs->blksz);
1264 file_inode->b.blocks.double_indir_block = di_blockno_parent; 1267 file_inode->b.blocks.double_indir_block = di_blockno_parent;
1265 } 1268 }
1266 fail: 1269 fail:
1267 free(di_block_start_addr); 1270 free(di_block_start_addr);
1268 } 1271 }
1269 1272
1270 static void alloc_triple_indirect_block(struct ext2_inode *file_inode, 1273 static void alloc_triple_indirect_block(struct ext2_inode *file_inode,
1271 unsigned int *total_remaining_blocks, 1274 unsigned int *total_remaining_blocks,
1272 unsigned int *no_blks_reqd) 1275 unsigned int *no_blks_reqd)
1273 { 1276 {
1274 short i; 1277 short i;
1275 short j; 1278 short j;
1276 short k; 1279 short k;
1277 long int actual_block_no; 1280 long int actual_block_no;
1278 /* ti: Triple Indirect */ 1281 /* ti: Triple Indirect */
1279 long int ti_gp_blockno; 1282 long int ti_gp_blockno;
1280 long int ti_parent_blockno; 1283 long int ti_parent_blockno;
1281 long int ti_child_blockno; 1284 long int ti_child_blockno;
1282 unsigned int *ti_gp_buff = NULL; 1285 unsigned int *ti_gp_buff = NULL;
1283 unsigned int *ti_parent_buff = NULL; 1286 unsigned int *ti_parent_buff = NULL;
1284 unsigned int *ti_child_buff = NULL; 1287 unsigned int *ti_child_buff = NULL;
1285 unsigned int *ti_gp_buff_start_addr = NULL; 1288 unsigned int *ti_gp_buff_start_addr = NULL;
1286 unsigned int *ti_pbuff_start_addr = NULL; 1289 unsigned int *ti_pbuff_start_addr = NULL;
1287 unsigned int *ti_cbuff_start_addr = NULL; 1290 unsigned int *ti_cbuff_start_addr = NULL;
1288 struct ext_filesystem *fs = get_fs(); 1291 struct ext_filesystem *fs = get_fs();
1289 if (*total_remaining_blocks != 0) { 1292 if (*total_remaining_blocks != 0) {
1290 /* triple indirect grand parent block connecting to inode */ 1293 /* triple indirect grand parent block connecting to inode */
1291 ti_gp_blockno = ext4fs_get_new_blk_no(); 1294 ti_gp_blockno = ext4fs_get_new_blk_no();
1292 if (ti_gp_blockno == -1) { 1295 if (ti_gp_blockno == -1) {
1293 printf("no block left to assign\n"); 1296 printf("no block left to assign\n");
1294 goto fail; 1297 goto fail;
1295 } 1298 }
1296 ti_gp_buff = zalloc(fs->blksz); 1299 ti_gp_buff = zalloc(fs->blksz);
1297 if (!ti_gp_buff) 1300 if (!ti_gp_buff)
1298 goto fail; 1301 goto fail;
1299 1302
1300 ti_gp_buff_start_addr = ti_gp_buff; 1303 ti_gp_buff_start_addr = ti_gp_buff;
1301 (*no_blks_reqd)++; 1304 (*no_blks_reqd)++;
1302 debug("TIGPB %ld: %u\n", ti_gp_blockno, 1305 debug("TIGPB %ld: %u\n", ti_gp_blockno,
1303 *total_remaining_blocks); 1306 *total_remaining_blocks);
1304 1307
1305 /* for each 4 byte grand parent entry create one more block */ 1308 /* for each 4 byte grand parent entry create one more block */
1306 for (i = 0; i < (fs->blksz / sizeof(int)); i++) { 1309 for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
1307 ti_parent_blockno = ext4fs_get_new_blk_no(); 1310 ti_parent_blockno = ext4fs_get_new_blk_no();
1308 if (ti_parent_blockno == -1) { 1311 if (ti_parent_blockno == -1) {
1309 printf("no block left to assign\n"); 1312 printf("no block left to assign\n");
1310 goto fail; 1313 goto fail;
1311 } 1314 }
1312 ti_parent_buff = zalloc(fs->blksz); 1315 ti_parent_buff = zalloc(fs->blksz);
1313 if (!ti_parent_buff) 1316 if (!ti_parent_buff)
1314 goto fail; 1317 goto fail;
1315 1318
1316 ti_pbuff_start_addr = ti_parent_buff; 1319 ti_pbuff_start_addr = ti_parent_buff;
1317 *ti_gp_buff = ti_parent_blockno; 1320 *ti_gp_buff = ti_parent_blockno;
1318 ti_gp_buff++; 1321 ti_gp_buff++;
1319 (*no_blks_reqd)++; 1322 (*no_blks_reqd)++;
1320 debug("TIPB %ld: %u\n", ti_parent_blockno, 1323 debug("TIPB %ld: %u\n", ti_parent_blockno,
1321 *total_remaining_blocks); 1324 *total_remaining_blocks);
1322 1325
1323 /* for each 4 byte entry parent create one more block */ 1326 /* for each 4 byte entry parent create one more block */
1324 for (j = 0; j < (fs->blksz / sizeof(int)); j++) { 1327 for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
1325 ti_child_blockno = ext4fs_get_new_blk_no(); 1328 ti_child_blockno = ext4fs_get_new_blk_no();
1326 if (ti_child_blockno == -1) { 1329 if (ti_child_blockno == -1) {
1327 printf("no block left assign\n"); 1330 printf("no block left assign\n");
1328 goto fail; 1331 goto fail;
1329 } 1332 }
1330 ti_child_buff = zalloc(fs->blksz); 1333 ti_child_buff = zalloc(fs->blksz);
1331 if (!ti_child_buff) 1334 if (!ti_child_buff)
1332 goto fail; 1335 goto fail;
1333 1336
1334 ti_cbuff_start_addr = ti_child_buff; 1337 ti_cbuff_start_addr = ti_child_buff;
1335 *ti_parent_buff = ti_child_blockno; 1338 *ti_parent_buff = ti_child_blockno;
1336 ti_parent_buff++; 1339 ti_parent_buff++;
1337 (*no_blks_reqd)++; 1340 (*no_blks_reqd)++;
1338 debug("TICB %ld: %u\n", ti_parent_blockno, 1341 debug("TICB %ld: %u\n", ti_parent_blockno,
1339 *total_remaining_blocks); 1342 *total_remaining_blocks);
1340 1343
1341 /* fill actual datablocks for each child */ 1344 /* fill actual datablocks for each child */
1342 for (k = 0; k < (fs->blksz / sizeof(int)); 1345 for (k = 0; k < (fs->blksz / sizeof(int));
1343 k++) { 1346 k++) {
1344 actual_block_no = 1347 actual_block_no =
1345 ext4fs_get_new_blk_no(); 1348 ext4fs_get_new_blk_no();
1346 if (actual_block_no == -1) { 1349 if (actual_block_no == -1) {
1347 printf("no block left\n"); 1350 printf("no block left\n");
1348 goto fail; 1351 goto fail;
1349 } 1352 }
1350 *ti_child_buff = actual_block_no; 1353 *ti_child_buff = actual_block_no;
1351 debug("TIAB %ld: %u\n", actual_block_no, 1354 debug("TIAB %ld: %u\n", actual_block_no,
1352 *total_remaining_blocks); 1355 *total_remaining_blocks);
1353 1356
1354 ti_child_buff++; 1357 ti_child_buff++;
1355 (*total_remaining_blocks)--; 1358 (*total_remaining_blocks)--;
1356 if (*total_remaining_blocks == 0) 1359 if (*total_remaining_blocks == 0)
1357 break; 1360 break;
1358 } 1361 }
1359 /* write the child block */ 1362 /* write the child block */
1360 put_ext4(((uint64_t) (ti_child_blockno * 1363 put_ext4(((uint64_t) (ti_child_blockno *
1361 fs->blksz)), 1364 fs->blksz)),
1362 ti_cbuff_start_addr, fs->blksz); 1365 ti_cbuff_start_addr, fs->blksz);
1363 free(ti_cbuff_start_addr); 1366 free(ti_cbuff_start_addr);
1364 1367
1365 if (*total_remaining_blocks == 0) 1368 if (*total_remaining_blocks == 0)
1366 break; 1369 break;
1367 } 1370 }
1368 /* write the parent block */ 1371 /* write the parent block */
1369 put_ext4(((uint64_t) (ti_parent_blockno * fs->blksz)), 1372 put_ext4(((uint64_t) (ti_parent_blockno * fs->blksz)),
1370 ti_pbuff_start_addr, fs->blksz); 1373 ti_pbuff_start_addr, fs->blksz);
1371 free(ti_pbuff_start_addr); 1374 free(ti_pbuff_start_addr);
1372 1375
1373 if (*total_remaining_blocks == 0) 1376 if (*total_remaining_blocks == 0)
1374 break; 1377 break;
1375 } 1378 }
1376 /* write the grand parent block */ 1379 /* write the grand parent block */
1377 put_ext4(((uint64_t) (ti_gp_blockno * fs->blksz)), 1380 put_ext4(((uint64_t) (ti_gp_blockno * fs->blksz)),
1378 ti_gp_buff_start_addr, fs->blksz); 1381 ti_gp_buff_start_addr, fs->blksz);
1379 file_inode->b.blocks.triple_indir_block = ti_gp_blockno; 1382 file_inode->b.blocks.triple_indir_block = ti_gp_blockno;
1380 } 1383 }
1381 fail: 1384 fail:
1382 free(ti_gp_buff_start_addr); 1385 free(ti_gp_buff_start_addr);
1383 } 1386 }
1384 1387
1385 void ext4fs_allocate_blocks(struct ext2_inode *file_inode, 1388 void ext4fs_allocate_blocks(struct ext2_inode *file_inode,
1386 unsigned int total_remaining_blocks, 1389 unsigned int total_remaining_blocks,
1387 unsigned int *total_no_of_block) 1390 unsigned int *total_no_of_block)
1388 { 1391 {
1389 short i; 1392 short i;
1390 long int direct_blockno; 1393 long int direct_blockno;
1391 unsigned int no_blks_reqd = 0; 1394 unsigned int no_blks_reqd = 0;
1392 1395
1393 /* allocation of direct blocks */ 1396 /* allocation of direct blocks */
1394 for (i = 0; i < INDIRECT_BLOCKS; i++) { 1397 for (i = 0; i < INDIRECT_BLOCKS; i++) {
1395 direct_blockno = ext4fs_get_new_blk_no(); 1398 direct_blockno = ext4fs_get_new_blk_no();
1396 if (direct_blockno == -1) { 1399 if (direct_blockno == -1) {
1397 printf("no block left to assign\n"); 1400 printf("no block left to assign\n");
1398 return; 1401 return;
1399 } 1402 }
1400 file_inode->b.blocks.dir_blocks[i] = direct_blockno; 1403 file_inode->b.blocks.dir_blocks[i] = direct_blockno;
1401 debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks); 1404 debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks);
1402 1405
1403 total_remaining_blocks--; 1406 total_remaining_blocks--;
1404 if (total_remaining_blocks == 0) 1407 if (total_remaining_blocks == 0)
1405 break; 1408 break;
1406 } 1409 }
1407 1410
1408 alloc_single_indirect_block(file_inode, &total_remaining_blocks, 1411 alloc_single_indirect_block(file_inode, &total_remaining_blocks,
1409 &no_blks_reqd); 1412 &no_blks_reqd);
1410 alloc_double_indirect_block(file_inode, &total_remaining_blocks, 1413 alloc_double_indirect_block(file_inode, &total_remaining_blocks,
1411 &no_blks_reqd); 1414 &no_blks_reqd);
1412 alloc_triple_indirect_block(file_inode, &total_remaining_blocks, 1415 alloc_triple_indirect_block(file_inode, &total_remaining_blocks,
1413 &no_blks_reqd); 1416 &no_blks_reqd);
1414 *total_no_of_block += no_blks_reqd; 1417 *total_no_of_block += no_blks_reqd;
1415 } 1418 }
1416 1419
1417 #endif 1420 #endif
1418 1421
1419 static struct ext4_extent_header *ext4fs_get_extent_block 1422 static struct ext4_extent_header *ext4fs_get_extent_block
1420 (struct ext2_data *data, char *buf, 1423 (struct ext2_data *data, char *buf,
1421 struct ext4_extent_header *ext_block, 1424 struct ext4_extent_header *ext_block,
1422 uint32_t fileblock, int log2_blksz) 1425 uint32_t fileblock, int log2_blksz)
1423 { 1426 {
1424 struct ext4_extent_idx *index; 1427 struct ext4_extent_idx *index;
1425 unsigned long long block; 1428 unsigned long long block;
1426 struct ext_filesystem *fs = get_fs(); 1429 struct ext_filesystem *fs = get_fs();
1427 int i; 1430 int i;
1428 1431
1429 while (1) { 1432 while (1) {
1430 index = (struct ext4_extent_idx *)(ext_block + 1); 1433 index = (struct ext4_extent_idx *)(ext_block + 1);
1431 1434
1432 if (le32_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) 1435 if (le32_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC)
1433 return 0; 1436 return 0;
1434 1437
1435 if (ext_block->eh_depth == 0) 1438 if (ext_block->eh_depth == 0)
1436 return ext_block; 1439 return ext_block;
1437 i = -1; 1440 i = -1;
1438 do { 1441 do {
1439 i++; 1442 i++;
1440 if (i >= le32_to_cpu(ext_block->eh_entries)) 1443 if (i >= le32_to_cpu(ext_block->eh_entries))
1441 break; 1444 break;
1442 } while (fileblock > le32_to_cpu(index[i].ei_block)); 1445 } while (fileblock > le32_to_cpu(index[i].ei_block));
1443 1446
1444 if (--i < 0) 1447 if (--i < 0)
1445 return 0; 1448 return 0;
1446 1449
1447 block = le32_to_cpu(index[i].ei_leaf_hi); 1450 block = le32_to_cpu(index[i].ei_leaf_hi);
1448 block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo); 1451 block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo);
1449 1452
1450 if (ext4fs_devread(block << log2_blksz, 0, fs->blksz, buf)) 1453 if (ext4fs_devread((lbaint_t)block << log2_blksz, 0, fs->blksz,
1454 buf))
1451 ext_block = (struct ext4_extent_header *)buf; 1455 ext_block = (struct ext4_extent_header *)buf;
1452 else 1456 else
1453 return 0; 1457 return 0;
1454 } 1458 }
1455 } 1459 }
1456 1460
1457 static int ext4fs_blockgroup 1461 static int ext4fs_blockgroup
1458 (struct ext2_data *data, int group, struct ext2_block_group *blkgrp) 1462 (struct ext2_data *data, int group, struct ext2_block_group *blkgrp)
1459 { 1463 {
1460 long int blkno; 1464 long int blkno;
1461 unsigned int blkoff, desc_per_blk; 1465 unsigned int blkoff, desc_per_blk;
1462 int log2blksz = get_fs()->dev_desc->log2blksz; 1466 int log2blksz = get_fs()->dev_desc->log2blksz;
1463 1467
1464 desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group); 1468 desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
1465 1469
1466 blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 + 1470 blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 +
1467 group / desc_per_blk; 1471 group / desc_per_blk;
1468 blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group); 1472 blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group);
1469 1473
1470 debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n", 1474 debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
1471 group, blkno, blkoff); 1475 group, blkno, blkoff);
1472 1476
1473 return ext4fs_devread(blkno << (LOG2_BLOCK_SIZE(data) - log2blksz), 1477 return ext4fs_devread((lbaint_t)blkno <<
1478 (LOG2_BLOCK_SIZE(data) - log2blksz),
1474 blkoff, sizeof(struct ext2_block_group), 1479 blkoff, sizeof(struct ext2_block_group),
1475 (char *)blkgrp); 1480 (char *)blkgrp);
1476 } 1481 }
1477 1482
1478 int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) 1483 int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)
1479 { 1484 {
1480 struct ext2_block_group blkgrp; 1485 struct ext2_block_group blkgrp;
1481 struct ext2_sblock *sblock = &data->sblock; 1486 struct ext2_sblock *sblock = &data->sblock;
1482 struct ext_filesystem *fs = get_fs(); 1487 struct ext_filesystem *fs = get_fs();
1483 int log2blksz = get_fs()->dev_desc->log2blksz; 1488 int log2blksz = get_fs()->dev_desc->log2blksz;
1484 int inodes_per_block, status; 1489 int inodes_per_block, status;
1485 long int blkno; 1490 long int blkno;
1486 unsigned int blkoff; 1491 unsigned int blkoff;
1487 1492
1488 /* It is easier to calculate if the first inode is 0. */ 1493 /* It is easier to calculate if the first inode is 0. */
1489 ino--; 1494 ino--;
1490 status = ext4fs_blockgroup(data, ino / __le32_to_cpu 1495 status = ext4fs_blockgroup(data, ino / __le32_to_cpu
1491 (sblock->inodes_per_group), &blkgrp); 1496 (sblock->inodes_per_group), &blkgrp);
1492 if (status == 0) 1497 if (status == 0)
1493 return 0; 1498 return 0;
1494 1499
1495 inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz; 1500 inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz;
1496 blkno = __le32_to_cpu(blkgrp.inode_table_id) + 1501 blkno = __le32_to_cpu(blkgrp.inode_table_id) +
1497 (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; 1502 (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
1498 blkoff = (ino % inodes_per_block) * fs->inodesz; 1503 blkoff = (ino % inodes_per_block) * fs->inodesz;
1499 /* Read the inode. */ 1504 /* Read the inode. */
1500 status = ext4fs_devread(blkno << (LOG2_BLOCK_SIZE(data) - log2blksz), 1505 status = ext4fs_devread((lbaint_t)blkno << (LOG2_BLOCK_SIZE(data) -
1501 blkoff, 1506 log2blksz), blkoff,
1502 sizeof(struct ext2_inode), (char *)inode); 1507 sizeof(struct ext2_inode), (char *)inode);
1503 if (status == 0) 1508 if (status == 0)
1504 return 0; 1509 return 0;
1505 1510
1506 return 1; 1511 return 1;
1507 } 1512 }
1508 1513
1509 long int read_allocated_block(struct ext2_inode *inode, int fileblock) 1514 long int read_allocated_block(struct ext2_inode *inode, int fileblock)
1510 { 1515 {
1511 long int blknr; 1516 long int blknr;
1512 int blksz; 1517 int blksz;
1513 int log2_blksz; 1518 int log2_blksz;
1514 int status; 1519 int status;
1515 long int rblock; 1520 long int rblock;
1516 long int perblock_parent; 1521 long int perblock_parent;
1517 long int perblock_child; 1522 long int perblock_child;
1518 unsigned long long start; 1523 unsigned long long start;
1519 /* get the blocksize of the filesystem */ 1524 /* get the blocksize of the filesystem */
1520 blksz = EXT2_BLOCK_SIZE(ext4fs_root); 1525 blksz = EXT2_BLOCK_SIZE(ext4fs_root);
1521 log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root) 1526 log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root)
1522 - get_fs()->dev_desc->log2blksz; 1527 - get_fs()->dev_desc->log2blksz;
1523 1528
1524 if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) { 1529 if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) {
1525 char *buf = zalloc(blksz); 1530 char *buf = zalloc(blksz);
1526 if (!buf) 1531 if (!buf)
1527 return -ENOMEM; 1532 return -ENOMEM;
1528 struct ext4_extent_header *ext_block; 1533 struct ext4_extent_header *ext_block;
1529 struct ext4_extent *extent; 1534 struct ext4_extent *extent;
1530 int i = -1; 1535 int i = -1;
1531 ext_block = 1536 ext_block =
1532 ext4fs_get_extent_block(ext4fs_root, buf, 1537 ext4fs_get_extent_block(ext4fs_root, buf,
1533 (struct ext4_extent_header *) 1538 (struct ext4_extent_header *)
1534 inode->b.blocks.dir_blocks, 1539 inode->b.blocks.dir_blocks,
1535 fileblock, log2_blksz); 1540 fileblock, log2_blksz);
1536 if (!ext_block) { 1541 if (!ext_block) {
1537 printf("invalid extent block\n"); 1542 printf("invalid extent block\n");
1538 free(buf); 1543 free(buf);
1539 return -EINVAL; 1544 return -EINVAL;
1540 } 1545 }
1541 1546
1542 extent = (struct ext4_extent *)(ext_block + 1); 1547 extent = (struct ext4_extent *)(ext_block + 1);
1543 1548
1544 do { 1549 do {
1545 i++; 1550 i++;
1546 if (i >= le32_to_cpu(ext_block->eh_entries)) 1551 if (i >= le32_to_cpu(ext_block->eh_entries))
1547 break; 1552 break;
1548 } while (fileblock >= le32_to_cpu(extent[i].ee_block)); 1553 } while (fileblock >= le32_to_cpu(extent[i].ee_block));
1549 if (--i >= 0) { 1554 if (--i >= 0) {
1550 fileblock -= le32_to_cpu(extent[i].ee_block); 1555 fileblock -= le32_to_cpu(extent[i].ee_block);
1551 if (fileblock >= le32_to_cpu(extent[i].ee_len)) { 1556 if (fileblock >= le32_to_cpu(extent[i].ee_len)) {
1552 free(buf); 1557 free(buf);
1553 return 0; 1558 return 0;
1554 } 1559 }
1555 1560
1556 start = le32_to_cpu(extent[i].ee_start_hi); 1561 start = le32_to_cpu(extent[i].ee_start_hi);
1557 start = (start << 32) + 1562 start = (start << 32) +
1558 le32_to_cpu(extent[i].ee_start_lo); 1563 le32_to_cpu(extent[i].ee_start_lo);
1559 free(buf); 1564 free(buf);
1560 return fileblock + start; 1565 return fileblock + start;
1561 } 1566 }
1562 1567
1563 printf("Extent Error\n"); 1568 printf("Extent Error\n");
1564 free(buf); 1569 free(buf);
1565 return -1; 1570 return -1;
1566 } 1571 }
1567 1572
1568 /* Direct blocks. */ 1573 /* Direct blocks. */
1569 if (fileblock < INDIRECT_BLOCKS) 1574 if (fileblock < INDIRECT_BLOCKS)
1570 blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]); 1575 blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]);
1571 1576
1572 /* Indirect. */ 1577 /* Indirect. */
1573 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) { 1578 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
1574 if (ext4fs_indir1_block == NULL) { 1579 if (ext4fs_indir1_block == NULL) {
1575 ext4fs_indir1_block = zalloc(blksz); 1580 ext4fs_indir1_block = zalloc(blksz);
1576 if (ext4fs_indir1_block == NULL) { 1581 if (ext4fs_indir1_block == NULL) {
1577 printf("** SI ext2fs read block (indir 1)" 1582 printf("** SI ext2fs read block (indir 1)"
1578 "malloc failed. **\n"); 1583 "malloc failed. **\n");
1579 return -1; 1584 return -1;
1580 } 1585 }
1581 ext4fs_indir1_size = blksz; 1586 ext4fs_indir1_size = blksz;
1582 ext4fs_indir1_blkno = -1; 1587 ext4fs_indir1_blkno = -1;
1583 } 1588 }
1584 if (blksz != ext4fs_indir1_size) { 1589 if (blksz != ext4fs_indir1_size) {
1585 free(ext4fs_indir1_block); 1590 free(ext4fs_indir1_block);
1586 ext4fs_indir1_block = NULL; 1591 ext4fs_indir1_block = NULL;
1587 ext4fs_indir1_size = 0; 1592 ext4fs_indir1_size = 0;
1588 ext4fs_indir1_blkno = -1; 1593 ext4fs_indir1_blkno = -1;
1589 ext4fs_indir1_block = zalloc(blksz); 1594 ext4fs_indir1_block = zalloc(blksz);
1590 if (ext4fs_indir1_block == NULL) { 1595 if (ext4fs_indir1_block == NULL) {
1591 printf("** SI ext2fs read block (indir 1):" 1596 printf("** SI ext2fs read block (indir 1):"
1592 "malloc failed. **\n"); 1597 "malloc failed. **\n");
1593 return -1; 1598 return -1;
1594 } 1599 }
1595 ext4fs_indir1_size = blksz; 1600 ext4fs_indir1_size = blksz;
1596 } 1601 }
1597 if ((__le32_to_cpu(inode->b.blocks.indir_block) << 1602 if ((__le32_to_cpu(inode->b.blocks.indir_block) <<
1598 log2_blksz) != ext4fs_indir1_blkno) { 1603 log2_blksz) != ext4fs_indir1_blkno) {
1599 status = 1604 status =
1600 ext4fs_devread(__le32_to_cpu 1605 ext4fs_devread((lbaint_t)__le32_to_cpu
1601 (inode->b.blocks. 1606 (inode->b.blocks.
1602 indir_block) << log2_blksz, 0, 1607 indir_block) << log2_blksz, 0,
1603 blksz, (char *)ext4fs_indir1_block); 1608 blksz, (char *)ext4fs_indir1_block);
1604 if (status == 0) { 1609 if (status == 0) {
1605 printf("** SI ext2fs read block (indir 1)" 1610 printf("** SI ext2fs read block (indir 1)"
1606 "failed. **\n"); 1611 "failed. **\n");
1607 return 0; 1612 return 0;
1608 } 1613 }
1609 ext4fs_indir1_blkno = 1614 ext4fs_indir1_blkno =
1610 __le32_to_cpu(inode->b.blocks. 1615 __le32_to_cpu(inode->b.blocks.
1611 indir_block) << log2_blksz; 1616 indir_block) << log2_blksz;
1612 } 1617 }
1613 blknr = __le32_to_cpu(ext4fs_indir1_block 1618 blknr = __le32_to_cpu(ext4fs_indir1_block
1614 [fileblock - INDIRECT_BLOCKS]); 1619 [fileblock - INDIRECT_BLOCKS]);
1615 } 1620 }
1616 /* Double indirect. */ 1621 /* Double indirect. */
1617 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 * 1622 else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 *
1618 (blksz / 4 + 1)))) { 1623 (blksz / 4 + 1)))) {
1619 1624
1620 long int perblock = blksz / 4; 1625 long int perblock = blksz / 4;
1621 long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4); 1626 long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);
1622 1627
1623 if (ext4fs_indir1_block == NULL) { 1628 if (ext4fs_indir1_block == NULL) {
1624 ext4fs_indir1_block = zalloc(blksz); 1629 ext4fs_indir1_block = zalloc(blksz);
1625 if (ext4fs_indir1_block == NULL) { 1630 if (ext4fs_indir1_block == NULL) {
1626 printf("** DI ext2fs read block (indir 2 1)" 1631 printf("** DI ext2fs read block (indir 2 1)"
1627 "malloc failed. **\n"); 1632 "malloc failed. **\n");
1628 return -1; 1633 return -1;
1629 } 1634 }
1630 ext4fs_indir1_size = blksz; 1635 ext4fs_indir1_size = blksz;
1631 ext4fs_indir1_blkno = -1; 1636 ext4fs_indir1_blkno = -1;
1632 } 1637 }
1633 if (blksz != ext4fs_indir1_size) { 1638 if (blksz != ext4fs_indir1_size) {
1634 free(ext4fs_indir1_block); 1639 free(ext4fs_indir1_block);
1635 ext4fs_indir1_block = NULL; 1640 ext4fs_indir1_block = NULL;
1636 ext4fs_indir1_size = 0; 1641 ext4fs_indir1_size = 0;
1637 ext4fs_indir1_blkno = -1; 1642 ext4fs_indir1_blkno = -1;
1638 ext4fs_indir1_block = zalloc(blksz); 1643 ext4fs_indir1_block = zalloc(blksz);
1639 if (ext4fs_indir1_block == NULL) { 1644 if (ext4fs_indir1_block == NULL) {
1640 printf("** DI ext2fs read block (indir 2 1)" 1645 printf("** DI ext2fs read block (indir 2 1)"
1641 "malloc failed. **\n"); 1646 "malloc failed. **\n");
1642 return -1; 1647 return -1;
1643 } 1648 }
1644 ext4fs_indir1_size = blksz; 1649 ext4fs_indir1_size = blksz;
1645 } 1650 }
1646 if ((__le32_to_cpu(inode->b.blocks.double_indir_block) << 1651 if ((__le32_to_cpu(inode->b.blocks.double_indir_block) <<
1647 log2_blksz) != ext4fs_indir1_blkno) { 1652 log2_blksz) != ext4fs_indir1_blkno) {
1648 status = 1653 status =
1649 ext4fs_devread(__le32_to_cpu 1654 ext4fs_devread((lbaint_t)__le32_to_cpu
1650 (inode->b.blocks. 1655 (inode->b.blocks.
1651 double_indir_block) << log2_blksz, 1656 double_indir_block) << log2_blksz,
1652 0, blksz, 1657 0, blksz,
1653 (char *)ext4fs_indir1_block); 1658 (char *)ext4fs_indir1_block);
1654 if (status == 0) { 1659 if (status == 0) {
1655 printf("** DI ext2fs read block (indir 2 1)" 1660 printf("** DI ext2fs read block (indir 2 1)"
1656 "failed. **\n"); 1661 "failed. **\n");
1657 return -1; 1662 return -1;
1658 } 1663 }
1659 ext4fs_indir1_blkno = 1664 ext4fs_indir1_blkno =
1660 __le32_to_cpu(inode->b.blocks.double_indir_block) << 1665 __le32_to_cpu(inode->b.blocks.double_indir_block) <<
1661 log2_blksz; 1666 log2_blksz;
1662 } 1667 }
1663 1668
1664 if (ext4fs_indir2_block == NULL) { 1669 if (ext4fs_indir2_block == NULL) {
1665 ext4fs_indir2_block = zalloc(blksz); 1670 ext4fs_indir2_block = zalloc(blksz);
1666 if (ext4fs_indir2_block == NULL) { 1671 if (ext4fs_indir2_block == NULL) {
1667 printf("** DI ext2fs read block (indir 2 2)" 1672 printf("** DI ext2fs read block (indir 2 2)"
1668 "malloc failed. **\n"); 1673 "malloc failed. **\n");
1669 return -1; 1674 return -1;
1670 } 1675 }
1671 ext4fs_indir2_size = blksz; 1676 ext4fs_indir2_size = blksz;
1672 ext4fs_indir2_blkno = -1; 1677 ext4fs_indir2_blkno = -1;
1673 } 1678 }
1674 if (blksz != ext4fs_indir2_size) { 1679 if (blksz != ext4fs_indir2_size) {
1675 free(ext4fs_indir2_block); 1680 free(ext4fs_indir2_block);
1676 ext4fs_indir2_block = NULL; 1681 ext4fs_indir2_block = NULL;
1677 ext4fs_indir2_size = 0; 1682 ext4fs_indir2_size = 0;
1678 ext4fs_indir2_blkno = -1; 1683 ext4fs_indir2_blkno = -1;
1679 ext4fs_indir2_block = zalloc(blksz); 1684 ext4fs_indir2_block = zalloc(blksz);
1680 if (ext4fs_indir2_block == NULL) { 1685 if (ext4fs_indir2_block == NULL) {
1681 printf("** DI ext2fs read block (indir 2 2)" 1686 printf("** DI ext2fs read block (indir 2 2)"
1682 "malloc failed. **\n"); 1687 "malloc failed. **\n");
1683 return -1; 1688 return -1;
1684 } 1689 }
1685 ext4fs_indir2_size = blksz; 1690 ext4fs_indir2_size = blksz;
1686 } 1691 }
1687 if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << 1692 if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) <<
1688 log2_blksz) != ext4fs_indir2_blkno) { 1693 log2_blksz) != ext4fs_indir2_blkno) {
1689 status = ext4fs_devread(__le32_to_cpu 1694 status = ext4fs_devread((lbaint_t)__le32_to_cpu
1690 (ext4fs_indir1_block 1695 (ext4fs_indir1_block
1691 [rblock / 1696 [rblock /
1692 perblock]) << log2_blksz, 0, 1697 perblock]) << log2_blksz, 0,
1693 blksz, 1698 blksz,
1694 (char *)ext4fs_indir2_block); 1699 (char *)ext4fs_indir2_block);
1695 if (status == 0) { 1700 if (status == 0) {
1696 printf("** DI ext2fs read block (indir 2 2)" 1701 printf("** DI ext2fs read block (indir 2 2)"
1697 "failed. **\n"); 1702 "failed. **\n");
1698 return -1; 1703 return -1;
1699 } 1704 }
1700 ext4fs_indir2_blkno = 1705 ext4fs_indir2_blkno =
1701 __le32_to_cpu(ext4fs_indir1_block[rblock 1706 __le32_to_cpu(ext4fs_indir1_block[rblock
1702 / 1707 /
1703 perblock]) << 1708 perblock]) <<
1704 log2_blksz; 1709 log2_blksz;
1705 } 1710 }
1706 blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]); 1711 blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]);
1707 } 1712 }
1708 /* Tripple indirect. */ 1713 /* Tripple indirect. */
1709 else { 1714 else {
1710 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + 1715 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 +
1711 (blksz / 4 * blksz / 4)); 1716 (blksz / 4 * blksz / 4));
1712 perblock_child = blksz / 4; 1717 perblock_child = blksz / 4;
1713 perblock_parent = ((blksz / 4) * (blksz / 4)); 1718 perblock_parent = ((blksz / 4) * (blksz / 4));
1714 1719
1715 if (ext4fs_indir1_block == NULL) { 1720 if (ext4fs_indir1_block == NULL) {
1716 ext4fs_indir1_block = zalloc(blksz); 1721 ext4fs_indir1_block = zalloc(blksz);
1717 if (ext4fs_indir1_block == NULL) { 1722 if (ext4fs_indir1_block == NULL) {
1718 printf("** TI ext2fs read block (indir 2 1)" 1723 printf("** TI ext2fs read block (indir 2 1)"
1719 "malloc failed. **\n"); 1724 "malloc failed. **\n");
1720 return -1; 1725 return -1;
1721 } 1726 }
1722 ext4fs_indir1_size = blksz; 1727 ext4fs_indir1_size = blksz;
1723 ext4fs_indir1_blkno = -1; 1728 ext4fs_indir1_blkno = -1;
1724 } 1729 }
1725 if (blksz != ext4fs_indir1_size) { 1730 if (blksz != ext4fs_indir1_size) {
1726 free(ext4fs_indir1_block); 1731 free(ext4fs_indir1_block);
1727 ext4fs_indir1_block = NULL; 1732 ext4fs_indir1_block = NULL;
1728 ext4fs_indir1_size = 0; 1733 ext4fs_indir1_size = 0;
1729 ext4fs_indir1_blkno = -1; 1734 ext4fs_indir1_blkno = -1;
1730 ext4fs_indir1_block = zalloc(blksz); 1735 ext4fs_indir1_block = zalloc(blksz);
1731 if (ext4fs_indir1_block == NULL) { 1736 if (ext4fs_indir1_block == NULL) {
1732 printf("** TI ext2fs read block (indir 2 1)" 1737 printf("** TI ext2fs read block (indir 2 1)"
1733 "malloc failed. **\n"); 1738 "malloc failed. **\n");
1734 return -1; 1739 return -1;
1735 } 1740 }
1736 ext4fs_indir1_size = blksz; 1741 ext4fs_indir1_size = blksz;
1737 } 1742 }
1738 if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) << 1743 if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) <<
1739 log2_blksz) != ext4fs_indir1_blkno) { 1744 log2_blksz) != ext4fs_indir1_blkno) {
1740 status = ext4fs_devread 1745 status = ext4fs_devread
1741 (__le32_to_cpu(inode->b.blocks.triple_indir_block) 1746 ((lbaint_t)
1747 __le32_to_cpu(inode->b.blocks.triple_indir_block)
1742 << log2_blksz, 0, blksz, 1748 << log2_blksz, 0, blksz,
1743 (char *)ext4fs_indir1_block); 1749 (char *)ext4fs_indir1_block);
1744 if (status == 0) { 1750 if (status == 0) {
1745 printf("** TI ext2fs read block (indir 2 1)" 1751 printf("** TI ext2fs read block (indir 2 1)"
1746 "failed. **\n"); 1752 "failed. **\n");
1747 return -1; 1753 return -1;
1748 } 1754 }
1749 ext4fs_indir1_blkno = 1755 ext4fs_indir1_blkno =
1750 __le32_to_cpu(inode->b.blocks.triple_indir_block) << 1756 __le32_to_cpu(inode->b.blocks.triple_indir_block) <<
1751 log2_blksz; 1757 log2_blksz;
1752 } 1758 }
1753 1759
1754 if (ext4fs_indir2_block == NULL) { 1760 if (ext4fs_indir2_block == NULL) {
1755 ext4fs_indir2_block = zalloc(blksz); 1761 ext4fs_indir2_block = zalloc(blksz);
1756 if (ext4fs_indir2_block == NULL) { 1762 if (ext4fs_indir2_block == NULL) {
1757 printf("** TI ext2fs read block (indir 2 2)" 1763 printf("** TI ext2fs read block (indir 2 2)"
1758 "malloc failed. **\n"); 1764 "malloc failed. **\n");
1759 return -1; 1765 return -1;
1760 } 1766 }
1761 ext4fs_indir2_size = blksz; 1767 ext4fs_indir2_size = blksz;
1762 ext4fs_indir2_blkno = -1; 1768 ext4fs_indir2_blkno = -1;
1763 } 1769 }
1764 if (blksz != ext4fs_indir2_size) { 1770 if (blksz != ext4fs_indir2_size) {
1765 free(ext4fs_indir2_block); 1771 free(ext4fs_indir2_block);
1766 ext4fs_indir2_block = NULL; 1772 ext4fs_indir2_block = NULL;
1767 ext4fs_indir2_size = 0; 1773 ext4fs_indir2_size = 0;
1768 ext4fs_indir2_blkno = -1; 1774 ext4fs_indir2_blkno = -1;
1769 ext4fs_indir2_block = zalloc(blksz); 1775 ext4fs_indir2_block = zalloc(blksz);
1770 if (ext4fs_indir2_block == NULL) { 1776 if (ext4fs_indir2_block == NULL) {
1771 printf("** TI ext2fs read block (indir 2 2)" 1777 printf("** TI ext2fs read block (indir 2 2)"
1772 "malloc failed. **\n"); 1778 "malloc failed. **\n");
1773 return -1; 1779 return -1;
1774 } 1780 }
1775 ext4fs_indir2_size = blksz; 1781 ext4fs_indir2_size = blksz;
1776 } 1782 }
1777 if ((__le32_to_cpu(ext4fs_indir1_block[rblock / 1783 if ((__le32_to_cpu(ext4fs_indir1_block[rblock /
1778 perblock_parent]) << 1784 perblock_parent]) <<
1779 log2_blksz) 1785 log2_blksz)
1780 != ext4fs_indir2_blkno) { 1786 != ext4fs_indir2_blkno) {
1781 status = ext4fs_devread(__le32_to_cpu 1787 status = ext4fs_devread((lbaint_t)__le32_to_cpu
1782 (ext4fs_indir1_block 1788 (ext4fs_indir1_block
1783 [rblock / 1789 [rblock /
1784 perblock_parent]) << 1790 perblock_parent]) <<
1785 log2_blksz, 0, blksz, 1791 log2_blksz, 0, blksz,
1786 (char *)ext4fs_indir2_block); 1792 (char *)ext4fs_indir2_block);
1787 if (status == 0) { 1793 if (status == 0) {
1788 printf("** TI ext2fs read block (indir 2 2)" 1794 printf("** TI ext2fs read block (indir 2 2)"
1789 "failed. **\n"); 1795 "failed. **\n");
1790 return -1; 1796 return -1;
1791 } 1797 }
1792 ext4fs_indir2_blkno = 1798 ext4fs_indir2_blkno =
1793 __le32_to_cpu(ext4fs_indir1_block[rblock / 1799 __le32_to_cpu(ext4fs_indir1_block[rblock /
1794 perblock_parent]) 1800 perblock_parent])
1795 << log2_blksz; 1801 << log2_blksz;
1796 } 1802 }
1797 1803
1798 if (ext4fs_indir3_block == NULL) { 1804 if (ext4fs_indir3_block == NULL) {
1799 ext4fs_indir3_block = zalloc(blksz); 1805 ext4fs_indir3_block = zalloc(blksz);
1800 if (ext4fs_indir3_block == NULL) { 1806 if (ext4fs_indir3_block == NULL) {
1801 printf("** TI ext2fs read block (indir 2 2)" 1807 printf("** TI ext2fs read block (indir 2 2)"
1802 "malloc failed. **\n"); 1808 "malloc failed. **\n");
1803 return -1; 1809 return -1;
1804 } 1810 }
1805 ext4fs_indir3_size = blksz; 1811 ext4fs_indir3_size = blksz;
1806 ext4fs_indir3_blkno = -1; 1812 ext4fs_indir3_blkno = -1;
1807 } 1813 }
1808 if (blksz != ext4fs_indir3_size) { 1814 if (blksz != ext4fs_indir3_size) {
1809 free(ext4fs_indir3_block); 1815 free(ext4fs_indir3_block);
1810 ext4fs_indir3_block = NULL; 1816 ext4fs_indir3_block = NULL;
1811 ext4fs_indir3_size = 0; 1817 ext4fs_indir3_size = 0;
1812 ext4fs_indir3_blkno = -1; 1818 ext4fs_indir3_blkno = -1;
1813 ext4fs_indir3_block = zalloc(blksz); 1819 ext4fs_indir3_block = zalloc(blksz);
1814 if (ext4fs_indir3_block == NULL) { 1820 if (ext4fs_indir3_block == NULL) {
1815 printf("** TI ext2fs read block (indir 2 2)" 1821 printf("** TI ext2fs read block (indir 2 2)"
1816 "malloc failed. **\n"); 1822 "malloc failed. **\n");
1817 return -1; 1823 return -1;
1818 } 1824 }
1819 ext4fs_indir3_size = blksz; 1825 ext4fs_indir3_size = blksz;
1820 } 1826 }
1821 if ((__le32_to_cpu(ext4fs_indir2_block[rblock 1827 if ((__le32_to_cpu(ext4fs_indir2_block[rblock
1822 / 1828 /
1823 perblock_child]) << 1829 perblock_child]) <<
1824 log2_blksz) != ext4fs_indir3_blkno) { 1830 log2_blksz) != ext4fs_indir3_blkno) {
1825 status = 1831 status =
1826 ext4fs_devread(__le32_to_cpu 1832 ext4fs_devread((lbaint_t)__le32_to_cpu
1827 (ext4fs_indir2_block 1833 (ext4fs_indir2_block
1828 [(rblock / perblock_child) 1834 [(rblock / perblock_child)
1829 % (blksz / 4)]) << log2_blksz, 0, 1835 % (blksz / 4)]) << log2_blksz, 0,
1830 blksz, (char *)ext4fs_indir3_block); 1836 blksz, (char *)ext4fs_indir3_block);
1831 if (status == 0) { 1837 if (status == 0) {
1832 printf("** TI ext2fs read block (indir 2 2)" 1838 printf("** TI ext2fs read block (indir 2 2)"
1833 "failed. **\n"); 1839 "failed. **\n");
1834 return -1; 1840 return -1;
1835 } 1841 }
1836 ext4fs_indir3_blkno = 1842 ext4fs_indir3_blkno =
1837 __le32_to_cpu(ext4fs_indir2_block[(rblock / 1843 __le32_to_cpu(ext4fs_indir2_block[(rblock /
1838 perblock_child) % 1844 perblock_child) %
1839 (blksz / 1845 (blksz /
1840 4)]) << 1846 4)]) <<
1841 log2_blksz; 1847 log2_blksz;
1842 } 1848 }
1843 1849
1844 blknr = __le32_to_cpu(ext4fs_indir3_block 1850 blknr = __le32_to_cpu(ext4fs_indir3_block
1845 [rblock % perblock_child]); 1851 [rblock % perblock_child]);
1846 } 1852 }
1847 debug("read_allocated_block %ld\n", blknr); 1853 debug("read_allocated_block %ld\n", blknr);
1848 1854
1849 return blknr; 1855 return blknr;
1850 } 1856 }
1851 1857
1852 void ext4fs_close(void) 1858 void ext4fs_close(void)
1853 { 1859 {
1854 if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) { 1860 if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) {
1855 ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen); 1861 ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen);
1856 ext4fs_file = NULL; 1862 ext4fs_file = NULL;
1857 } 1863 }
1858 if (ext4fs_root != NULL) { 1864 if (ext4fs_root != NULL) {
1859 free(ext4fs_root); 1865 free(ext4fs_root);
1860 ext4fs_root = NULL; 1866 ext4fs_root = NULL;
1861 } 1867 }
1862 if (ext4fs_indir1_block != NULL) { 1868 if (ext4fs_indir1_block != NULL) {
1863 free(ext4fs_indir1_block); 1869 free(ext4fs_indir1_block);
1864 ext4fs_indir1_block = NULL; 1870 ext4fs_indir1_block = NULL;
1865 ext4fs_indir1_size = 0; 1871 ext4fs_indir1_size = 0;
1866 ext4fs_indir1_blkno = -1; 1872 ext4fs_indir1_blkno = -1;
1867 } 1873 }
1868 if (ext4fs_indir2_block != NULL) { 1874 if (ext4fs_indir2_block != NULL) {
1869 free(ext4fs_indir2_block); 1875 free(ext4fs_indir2_block);
1870 ext4fs_indir2_block = NULL; 1876 ext4fs_indir2_block = NULL;
1871 ext4fs_indir2_size = 0; 1877 ext4fs_indir2_size = 0;
1872 ext4fs_indir2_blkno = -1; 1878 ext4fs_indir2_blkno = -1;
1873 } 1879 }
1874 if (ext4fs_indir3_block != NULL) { 1880 if (ext4fs_indir3_block != NULL) {
1875 free(ext4fs_indir3_block); 1881 free(ext4fs_indir3_block);
1876 ext4fs_indir3_block = NULL; 1882 ext4fs_indir3_block = NULL;
1877 ext4fs_indir3_size = 0; 1883 ext4fs_indir3_size = 0;
1878 ext4fs_indir3_blkno = -1; 1884 ext4fs_indir3_blkno = -1;
1879 } 1885 }
1880 } 1886 }
1881 1887
1882 int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, 1888 int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
1883 struct ext2fs_node **fnode, int *ftype) 1889 struct ext2fs_node **fnode, int *ftype)
1884 { 1890 {
1885 unsigned int fpos = 0; 1891 unsigned int fpos = 0;
1886 int status; 1892 int status;
1887 struct ext2fs_node *diro = (struct ext2fs_node *) dir; 1893 struct ext2fs_node *diro = (struct ext2fs_node *) dir;
1888 1894
1889 #ifdef DEBUG 1895 #ifdef DEBUG
1890 if (name != NULL) 1896 if (name != NULL)
1891 printf("Iterate dir %s\n", name); 1897 printf("Iterate dir %s\n", name);
1892 #endif /* of DEBUG */ 1898 #endif /* of DEBUG */
1893 if (!diro->inode_read) { 1899 if (!diro->inode_read) {
1894 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); 1900 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
1895 if (status == 0) 1901 if (status == 0)
1896 return 0; 1902 return 0;
1897 } 1903 }
1898 /* Search the file. */ 1904 /* Search the file. */
1899 while (fpos < __le32_to_cpu(diro->inode.size)) { 1905 while (fpos < __le32_to_cpu(diro->inode.size)) {
1900 struct ext2_dirent dirent; 1906 struct ext2_dirent dirent;
1901 1907
1902 status = ext4fs_read_file(diro, fpos, 1908 status = ext4fs_read_file(diro, fpos,
1903 sizeof(struct ext2_dirent), 1909 sizeof(struct ext2_dirent),
1904 (char *) &dirent); 1910 (char *) &dirent);
1905 if (status < 1) 1911 if (status < 1)
1906 return 0; 1912 return 0;
1907 1913
1908 if (dirent.namelen != 0) { 1914 if (dirent.namelen != 0) {
1909 char filename[dirent.namelen + 1]; 1915 char filename[dirent.namelen + 1];
1910 struct ext2fs_node *fdiro; 1916 struct ext2fs_node *fdiro;
1911 int type = FILETYPE_UNKNOWN; 1917 int type = FILETYPE_UNKNOWN;
1912 1918
1913 status = ext4fs_read_file(diro, 1919 status = ext4fs_read_file(diro,
1914 fpos + 1920 fpos +
1915 sizeof(struct ext2_dirent), 1921 sizeof(struct ext2_dirent),
1916 dirent.namelen, filename); 1922 dirent.namelen, filename);
1917 if (status < 1) 1923 if (status < 1)
1918 return 0; 1924 return 0;
1919 1925
1920 fdiro = zalloc(sizeof(struct ext2fs_node)); 1926 fdiro = zalloc(sizeof(struct ext2fs_node));
1921 if (!fdiro) 1927 if (!fdiro)
1922 return 0; 1928 return 0;
1923 1929
1924 fdiro->data = diro->data; 1930 fdiro->data = diro->data;
1925 fdiro->ino = __le32_to_cpu(dirent.inode); 1931 fdiro->ino = __le32_to_cpu(dirent.inode);
1926 1932
1927 filename[dirent.namelen] = '\0'; 1933 filename[dirent.namelen] = '\0';
1928 1934
1929 if (dirent.filetype != FILETYPE_UNKNOWN) { 1935 if (dirent.filetype != FILETYPE_UNKNOWN) {
1930 fdiro->inode_read = 0; 1936 fdiro->inode_read = 0;
1931 1937
1932 if (dirent.filetype == FILETYPE_DIRECTORY) 1938 if (dirent.filetype == FILETYPE_DIRECTORY)
1933 type = FILETYPE_DIRECTORY; 1939 type = FILETYPE_DIRECTORY;
1934 else if (dirent.filetype == FILETYPE_SYMLINK) 1940 else if (dirent.filetype == FILETYPE_SYMLINK)
1935 type = FILETYPE_SYMLINK; 1941 type = FILETYPE_SYMLINK;
1936 else if (dirent.filetype == FILETYPE_REG) 1942 else if (dirent.filetype == FILETYPE_REG)
1937 type = FILETYPE_REG; 1943 type = FILETYPE_REG;
1938 } else { 1944 } else {
1939 status = ext4fs_read_inode(diro->data, 1945 status = ext4fs_read_inode(diro->data,
1940 __le32_to_cpu 1946 __le32_to_cpu
1941 (dirent.inode), 1947 (dirent.inode),
1942 &fdiro->inode); 1948 &fdiro->inode);
1943 if (status == 0) { 1949 if (status == 0) {
1944 free(fdiro); 1950 free(fdiro);
1945 return 0; 1951 return 0;
1946 } 1952 }
1947 fdiro->inode_read = 1; 1953 fdiro->inode_read = 1;
1948 1954
1949 if ((__le16_to_cpu(fdiro->inode.mode) & 1955 if ((__le16_to_cpu(fdiro->inode.mode) &
1950 FILETYPE_INO_MASK) == 1956 FILETYPE_INO_MASK) ==
1951 FILETYPE_INO_DIRECTORY) { 1957 FILETYPE_INO_DIRECTORY) {
1952 type = FILETYPE_DIRECTORY; 1958 type = FILETYPE_DIRECTORY;
1953 } else if ((__le16_to_cpu(fdiro->inode.mode) 1959 } else if ((__le16_to_cpu(fdiro->inode.mode)
1954 & FILETYPE_INO_MASK) == 1960 & FILETYPE_INO_MASK) ==
1955 FILETYPE_INO_SYMLINK) { 1961 FILETYPE_INO_SYMLINK) {
1956 type = FILETYPE_SYMLINK; 1962 type = FILETYPE_SYMLINK;
1957 } else if ((__le16_to_cpu(fdiro->inode.mode) 1963 } else if ((__le16_to_cpu(fdiro->inode.mode)
1958 & FILETYPE_INO_MASK) == 1964 & FILETYPE_INO_MASK) ==
1959 FILETYPE_INO_REG) { 1965 FILETYPE_INO_REG) {
1960 type = FILETYPE_REG; 1966 type = FILETYPE_REG;
1961 } 1967 }
1962 } 1968 }
1963 #ifdef DEBUG 1969 #ifdef DEBUG
1964 printf("iterate >%s<\n", filename); 1970 printf("iterate >%s<\n", filename);
1965 #endif /* of DEBUG */ 1971 #endif /* of DEBUG */
1966 if ((name != NULL) && (fnode != NULL) 1972 if ((name != NULL) && (fnode != NULL)
1967 && (ftype != NULL)) { 1973 && (ftype != NULL)) {
1968 if (strcmp(filename, name) == 0) { 1974 if (strcmp(filename, name) == 0) {
1969 *ftype = type; 1975 *ftype = type;
1970 *fnode = fdiro; 1976 *fnode = fdiro;
1971 return 1; 1977 return 1;
1972 } 1978 }
1973 } else { 1979 } else {
1974 if (fdiro->inode_read == 0) { 1980 if (fdiro->inode_read == 0) {
1975 status = ext4fs_read_inode(diro->data, 1981 status = ext4fs_read_inode(diro->data,
1976 __le32_to_cpu( 1982 __le32_to_cpu(
1977 dirent.inode), 1983 dirent.inode),
1978 &fdiro->inode); 1984 &fdiro->inode);
1979 if (status == 0) { 1985 if (status == 0) {
1980 free(fdiro); 1986 free(fdiro);
1981 return 0; 1987 return 0;
1982 } 1988 }
1983 fdiro->inode_read = 1; 1989 fdiro->inode_read = 1;
1984 } 1990 }
1985 switch (type) { 1991 switch (type) {
1986 case FILETYPE_DIRECTORY: 1992 case FILETYPE_DIRECTORY:
1987 printf("<DIR> "); 1993 printf("<DIR> ");
1988 break; 1994 break;
1989 case FILETYPE_SYMLINK: 1995 case FILETYPE_SYMLINK:
1990 printf("<SYM> "); 1996 printf("<SYM> ");
1991 break; 1997 break;
1992 case FILETYPE_REG: 1998 case FILETYPE_REG:
1993 printf(" "); 1999 printf(" ");
1994 break; 2000 break;
1995 default: 2001 default:
1996 printf("< ? > "); 2002 printf("< ? > ");
1997 break; 2003 break;
1998 } 2004 }
1999 printf("%10d %s\n", 2005 printf("%10d %s\n",
2000 __le32_to_cpu(fdiro->inode.size), 2006 __le32_to_cpu(fdiro->inode.size),
2001 filename); 2007 filename);
2002 } 2008 }
2003 free(fdiro); 2009 free(fdiro);
2004 } 2010 }
2005 fpos += __le16_to_cpu(dirent.direntlen); 2011 fpos += __le16_to_cpu(dirent.direntlen);
2006 } 2012 }
2007 return 0; 2013 return 0;
2008 } 2014 }
2009 2015
2010 static char *ext4fs_read_symlink(struct ext2fs_node *node) 2016 static char *ext4fs_read_symlink(struct ext2fs_node *node)
2011 { 2017 {
2012 char *symlink; 2018 char *symlink;
2013 struct ext2fs_node *diro = node; 2019 struct ext2fs_node *diro = node;
2014 int status; 2020 int status;
2015 2021
2016 if (!diro->inode_read) { 2022 if (!diro->inode_read) {
2017 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); 2023 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
2018 if (status == 0) 2024 if (status == 0)
2019 return 0; 2025 return 0;
2020 } 2026 }
2021 symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1); 2027 symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1);
2022 if (!symlink) 2028 if (!symlink)
2023 return 0; 2029 return 0;
2024 2030
2025 if (__le32_to_cpu(diro->inode.size) <= 60) { 2031 if (__le32_to_cpu(diro->inode.size) <= 60) {
2026 strncpy(symlink, diro->inode.b.symlink, 2032 strncpy(symlink, diro->inode.b.symlink,
2027 __le32_to_cpu(diro->inode.size)); 2033 __le32_to_cpu(diro->inode.size));
2028 } else { 2034 } else {
2029 status = ext4fs_read_file(diro, 0, 2035 status = ext4fs_read_file(diro, 0,
2030 __le32_to_cpu(diro->inode.size), 2036 __le32_to_cpu(diro->inode.size),
2031 symlink); 2037 symlink);
2032 if (status == 0) { 2038 if (status == 0) {
2033 free(symlink); 2039 free(symlink);
2034 return 0; 2040 return 0;
2035 } 2041 }
2036 } 2042 }
2037 symlink[__le32_to_cpu(diro->inode.size)] = '\0'; 2043 symlink[__le32_to_cpu(diro->inode.size)] = '\0';
2038 return symlink; 2044 return symlink;
2039 } 2045 }
2040 2046
2041 static int ext4fs_find_file1(const char *currpath, 2047 static int ext4fs_find_file1(const char *currpath,
2042 struct ext2fs_node *currroot, 2048 struct ext2fs_node *currroot,
2043 struct ext2fs_node **currfound, int *foundtype) 2049 struct ext2fs_node **currfound, int *foundtype)
2044 { 2050 {
2045 char fpath[strlen(currpath) + 1]; 2051 char fpath[strlen(currpath) + 1];
2046 char *name = fpath; 2052 char *name = fpath;
2047 char *next; 2053 char *next;
2048 int status; 2054 int status;
2049 int type = FILETYPE_DIRECTORY; 2055 int type = FILETYPE_DIRECTORY;
2050 struct ext2fs_node *currnode = currroot; 2056 struct ext2fs_node *currnode = currroot;
2051 struct ext2fs_node *oldnode = currroot; 2057 struct ext2fs_node *oldnode = currroot;
2052 2058
2053 strncpy(fpath, currpath, strlen(currpath) + 1); 2059 strncpy(fpath, currpath, strlen(currpath) + 1);
2054 2060
2055 /* Remove all leading slashes. */ 2061 /* Remove all leading slashes. */
2056 while (*name == '/') 2062 while (*name == '/')
2057 name++; 2063 name++;
2058 2064
2059 if (!*name) { 2065 if (!*name) {
2060 *currfound = currnode; 2066 *currfound = currnode;
2061 return 1; 2067 return 1;
2062 } 2068 }
2063 2069
2064 for (;;) { 2070 for (;;) {
2065 int found; 2071 int found;
2066 2072
2067 /* Extract the actual part from the pathname. */ 2073 /* Extract the actual part from the pathname. */
2068 next = strchr(name, '/'); 2074 next = strchr(name, '/');
2069 if (next) { 2075 if (next) {
2070 /* Remove all leading slashes. */ 2076 /* Remove all leading slashes. */
2071 while (*next == '/') 2077 while (*next == '/')
2072 *(next++) = '\0'; 2078 *(next++) = '\0';
2073 } 2079 }
2074 2080
2075 if (type != FILETYPE_DIRECTORY) { 2081 if (type != FILETYPE_DIRECTORY) {
2076 ext4fs_free_node(currnode, currroot); 2082 ext4fs_free_node(currnode, currroot);
2077 return 0; 2083 return 0;
2078 } 2084 }
2079 2085
2080 oldnode = currnode; 2086 oldnode = currnode;
2081 2087
2082 /* Iterate over the directory. */ 2088 /* Iterate over the directory. */
2083 found = ext4fs_iterate_dir(currnode, name, &currnode, &type); 2089 found = ext4fs_iterate_dir(currnode, name, &currnode, &type);
2084 if (found == 0) 2090 if (found == 0)
2085 return 0; 2091 return 0;
2086 2092
2087 if (found == -1) 2093 if (found == -1)
2088 break; 2094 break;
2089 2095
2090 /* Read in the symlink and follow it. */ 2096 /* Read in the symlink and follow it. */
2091 if (type == FILETYPE_SYMLINK) { 2097 if (type == FILETYPE_SYMLINK) {
2092 char *symlink; 2098 char *symlink;
2093 2099
2094 /* Test if the symlink does not loop. */ 2100 /* Test if the symlink does not loop. */
2095 if (++symlinknest == 8) { 2101 if (++symlinknest == 8) {
2096 ext4fs_free_node(currnode, currroot); 2102 ext4fs_free_node(currnode, currroot);
2097 ext4fs_free_node(oldnode, currroot); 2103 ext4fs_free_node(oldnode, currroot);
2098 return 0; 2104 return 0;
2099 } 2105 }
2100 2106
2101 symlink = ext4fs_read_symlink(currnode); 2107 symlink = ext4fs_read_symlink(currnode);
2102 ext4fs_free_node(currnode, currroot); 2108 ext4fs_free_node(currnode, currroot);
2103 2109
2104 if (!symlink) { 2110 if (!symlink) {
2105 ext4fs_free_node(oldnode, currroot); 2111 ext4fs_free_node(oldnode, currroot);
2106 return 0; 2112 return 0;
2107 } 2113 }
2108 2114
2109 debug("Got symlink >%s<\n", symlink); 2115 debug("Got symlink >%s<\n", symlink);
2110 2116
2111 if (symlink[0] == '/') { 2117 if (symlink[0] == '/') {
2112 ext4fs_free_node(oldnode, currroot); 2118 ext4fs_free_node(oldnode, currroot);
2113 oldnode = &ext4fs_root->diropen; 2119 oldnode = &ext4fs_root->diropen;
2114 } 2120 }
2115 2121
2116 /* Lookup the node the symlink points to. */ 2122 /* Lookup the node the symlink points to. */
2117 status = ext4fs_find_file1(symlink, oldnode, 2123 status = ext4fs_find_file1(symlink, oldnode,
2118 &currnode, &type); 2124 &currnode, &type);
2119 2125
2120 free(symlink); 2126 free(symlink);
2121 2127
2122 if (status == 0) { 2128 if (status == 0) {
2123 ext4fs_free_node(oldnode, currroot); 2129 ext4fs_free_node(oldnode, currroot);
2124 return 0; 2130 return 0;
2125 } 2131 }
2126 } 2132 }
2127 2133
2128 ext4fs_free_node(oldnode, currroot); 2134 ext4fs_free_node(oldnode, currroot);
2129 2135
2130 /* Found the node! */ 2136 /* Found the node! */
2131 if (!next || *next == '\0') { 2137 if (!next || *next == '\0') {
2132 *currfound = currnode; 2138 *currfound = currnode;
2133 *foundtype = type; 2139 *foundtype = type;
2134 return 1; 2140 return 1;
2135 } 2141 }
2136 name = next; 2142 name = next;
2137 } 2143 }
2138 return -1; 2144 return -1;
2139 } 2145 }
2140 2146
2141 int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, 2147 int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
2142 struct ext2fs_node **foundnode, int expecttype) 2148 struct ext2fs_node **foundnode, int expecttype)
2143 { 2149 {
2144 int status; 2150 int status;
2145 int foundtype = FILETYPE_DIRECTORY; 2151 int foundtype = FILETYPE_DIRECTORY;
2146 2152
2147 symlinknest = 0; 2153 symlinknest = 0;
2148 if (!path) 2154 if (!path)
2149 return 0; 2155 return 0;
2150 2156
2151 status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype); 2157 status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype);
2152 if (status == 0) 2158 if (status == 0)
2153 return 0; 2159 return 0;
2154 2160
2155 /* Check if the node that was found was of the expected type. */ 2161 /* Check if the node that was found was of the expected type. */
2156 if ((expecttype == FILETYPE_REG) && (foundtype != expecttype)) 2162 if ((expecttype == FILETYPE_REG) && (foundtype != expecttype))
2157 return 0; 2163 return 0;
2158 else if ((expecttype == FILETYPE_DIRECTORY) 2164 else if ((expecttype == FILETYPE_DIRECTORY)
2159 && (foundtype != expecttype)) 2165 && (foundtype != expecttype))
2160 return 0; 2166 return 0;
2161 2167
2162 return 1; 2168 return 1;
2163 } 2169 }
2164 2170
2165 int ext4fs_open(const char *filename) 2171 int ext4fs_open(const char *filename)
2166 { 2172 {
2167 struct ext2fs_node *fdiro = NULL; 2173 struct ext2fs_node *fdiro = NULL;
2168 int status; 2174 int status;
2169 int len; 2175 int len;
2170 2176
2171 if (ext4fs_root == NULL) 2177 if (ext4fs_root == NULL)
2172 return -1; 2178 return -1;
2173 2179
2174 ext4fs_file = NULL; 2180 ext4fs_file = NULL;
2175 status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro, 2181 status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro,
2176 FILETYPE_REG); 2182 FILETYPE_REG);
2177 if (status == 0) 2183 if (status == 0)
2178 goto fail; 2184 goto fail;
2179 2185
2180 if (!fdiro->inode_read) { 2186 if (!fdiro->inode_read) {
2181 status = ext4fs_read_inode(fdiro->data, fdiro->ino, 2187 status = ext4fs_read_inode(fdiro->data, fdiro->ino,
2182 &fdiro->inode); 2188 &fdiro->inode);
2183 if (status == 0) 2189 if (status == 0)
2184 goto fail; 2190 goto fail;
2185 } 2191 }
2186 len = __le32_to_cpu(fdiro->inode.size); 2192 len = __le32_to_cpu(fdiro->inode.size);
2187 ext4fs_file = fdiro; 2193 ext4fs_file = fdiro;
2188 2194
2189 return len; 2195 return len;
2190 fail: 2196 fail:
2191 ext4fs_free_node(fdiro, &ext4fs_root->diropen); 2197 ext4fs_free_node(fdiro, &ext4fs_root->diropen);
2192 2198
2193 return -1; 2199 return -1;
2194 } 2200 }
2195 2201
2196 int ext4fs_mount(unsigned part_length) 2202 int ext4fs_mount(unsigned part_length)
2197 { 2203 {
2198 struct ext2_data *data; 2204 struct ext2_data *data;
2199 int status; 2205 int status;
2200 struct ext_filesystem *fs = get_fs(); 2206 struct ext_filesystem *fs = get_fs();
2201 data = zalloc(SUPERBLOCK_SIZE); 2207 data = zalloc(SUPERBLOCK_SIZE);
2202 if (!data) 2208 if (!data)
2203 return 0; 2209 return 0;
2204 2210
2205 /* Read the superblock. */ 2211 /* Read the superblock. */
2206 status = ext4_read_superblock((char *)&data->sblock); 2212 status = ext4_read_superblock((char *)&data->sblock);
2207 2213
2208 if (status == 0) 2214 if (status == 0)
2209 goto fail; 2215 goto fail;
2210 2216
2211 /* Make sure this is an ext2 filesystem. */ 2217 /* Make sure this is an ext2 filesystem. */
2212 if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC) 2218 if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC)
2213 goto fail; 2219 goto fail;
2214 2220
2215 if (__le32_to_cpu(data->sblock.revision_level == 0)) 2221 if (__le32_to_cpu(data->sblock.revision_level == 0))
2216 fs->inodesz = 128; 2222 fs->inodesz = 128;
2217 else 2223 else
2218 fs->inodesz = __le16_to_cpu(data->sblock.inode_size); 2224 fs->inodesz = __le16_to_cpu(data->sblock.inode_size);
2219 2225
2220 debug("EXT2 rev %d, inode_size %d\n", 2226 debug("EXT2 rev %d, inode_size %d\n",
2221 __le32_to_cpu(data->sblock.revision_level), fs->inodesz); 2227 __le32_to_cpu(data->sblock.revision_level), fs->inodesz);
2222 2228
2223 data->diropen.data = data; 2229 data->diropen.data = data;
2224 data->diropen.ino = 2; 2230 data->diropen.ino = 2;
2225 data->diropen.inode_read = 1; 2231 data->diropen.inode_read = 1;
2226 data->inode = &data->diropen.inode; 2232 data->inode = &data->diropen.inode;
2227 2233
2228 status = ext4fs_read_inode(data, 2, data->inode); 2234 status = ext4fs_read_inode(data, 2, data->inode);
2229 if (status == 0) 2235 if (status == 0)
2230 goto fail; 2236 goto fail;
2231 2237
2232 ext4fs_root = data; 2238 ext4fs_root = data;
2233 2239
2234 return 1; 2240 return 1;
2235 fail: 2241 fail:
2236 printf("Failed to mount ext2 filesystem...\n"); 2242 printf("Failed to mount ext2 filesystem...\n");
2237 free(data); 2243 free(data);
2238 ext4fs_root = NULL; 2244 ext4fs_root = NULL;
2239 2245
2240 return 0; 2246 return 0;
2241 } 2247 }
2242 2248
fs/ext4/ext4_journal.c
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * Journal data structures and headers for Journaling feature of ext4 7 * Journal data structures and headers for Journaling feature of ext4
8 * have been referred from JBD2 (Journaling Block device 2) 8 * have been referred from JBD2 (Journaling Block device 2)
9 * implementation in Linux Kernel. 9 * implementation in Linux Kernel.
10 * Written by Stephen C. Tweedie <sct@redhat.com> 10 * Written by Stephen C. Tweedie <sct@redhat.com>
11 * 11 *
12 * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved 12 * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
13 * This file is part of the Linux kernel and is made available under 13 * This file is part of the Linux kernel and is made available under
14 * the terms of the GNU General Public License, version 2, or at your 14 * the terms of the GNU General Public License, version 2, or at your
15 * option, any later version, incorporated herein by reference. 15 * option, any later version, incorporated herein by reference.
16 * 16 *
17 * This program is free software; you can redistribute it and/or modify 17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by 18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or 19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version. 20 * (at your option) any later version.
21 * 21 *
22 * This program is distributed in the hope that it will be useful, 22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details. 25 * GNU General Public License for more details.
26 * 26 *
27 * You should have received a copy of the GNU General Public License 27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software 28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 */ 30 */
31 31
32 #include <common.h> 32 #include <common.h>
33 #include <ext4fs.h> 33 #include <ext4fs.h>
34 #include <malloc.h> 34 #include <malloc.h>
35 #include <ext_common.h> 35 #include <ext_common.h>
36 #include "ext4_common.h" 36 #include "ext4_common.h"
37 37
38 static struct revoke_blk_list *revk_blk_list; 38 static struct revoke_blk_list *revk_blk_list;
39 static struct revoke_blk_list *prev_node; 39 static struct revoke_blk_list *prev_node;
40 static int first_node = true; 40 static int first_node = true;
41 41
42 int gindex; 42 int gindex;
43 int gd_index; 43 int gd_index;
44 int jrnl_blk_idx; 44 int jrnl_blk_idx;
45 struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES]; 45 struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES];
46 struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES]; 46 struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES];
47 47
48 int ext4fs_init_journal(void) 48 int ext4fs_init_journal(void)
49 { 49 {
50 int i; 50 int i;
51 char *temp = NULL; 51 char *temp = NULL;
52 struct ext_filesystem *fs = get_fs(); 52 struct ext_filesystem *fs = get_fs();
53 53
54 /* init globals */ 54 /* init globals */
55 revk_blk_list = NULL; 55 revk_blk_list = NULL;
56 prev_node = NULL; 56 prev_node = NULL;
57 gindex = 0; 57 gindex = 0;
58 gd_index = 0; 58 gd_index = 0;
59 jrnl_blk_idx = 1; 59 jrnl_blk_idx = 1;
60 60
61 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { 61 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
62 journal_ptr[i] = zalloc(sizeof(struct journal_log)); 62 journal_ptr[i] = zalloc(sizeof(struct journal_log));
63 if (!journal_ptr[i]) 63 if (!journal_ptr[i])
64 goto fail; 64 goto fail;
65 dirty_block_ptr[i] = zalloc(sizeof(struct dirty_blocks)); 65 dirty_block_ptr[i] = zalloc(sizeof(struct dirty_blocks));
66 if (!dirty_block_ptr[i]) 66 if (!dirty_block_ptr[i])
67 goto fail; 67 goto fail;
68 journal_ptr[i]->buf = NULL; 68 journal_ptr[i]->buf = NULL;
69 journal_ptr[i]->blknr = -1; 69 journal_ptr[i]->blknr = -1;
70 70
71 dirty_block_ptr[i]->buf = NULL; 71 dirty_block_ptr[i]->buf = NULL;
72 dirty_block_ptr[i]->blknr = -1; 72 dirty_block_ptr[i]->blknr = -1;
73 } 73 }
74 74
75 if (fs->blksz == 4096) { 75 if (fs->blksz == 4096) {
76 temp = zalloc(fs->blksz); 76 temp = zalloc(fs->blksz);
77 if (!temp) 77 if (!temp)
78 goto fail; 78 goto fail;
79 journal_ptr[gindex]->buf = zalloc(fs->blksz); 79 journal_ptr[gindex]->buf = zalloc(fs->blksz);
80 if (!journal_ptr[gindex]->buf) 80 if (!journal_ptr[gindex]->buf)
81 goto fail; 81 goto fail;
82 ext4fs_devread(0, 0, fs->blksz, temp); 82 ext4fs_devread(0, 0, fs->blksz, temp);
83 memcpy(temp + SUPERBLOCK_SIZE, fs->sb, SUPERBLOCK_SIZE); 83 memcpy(temp + SUPERBLOCK_SIZE, fs->sb, SUPERBLOCK_SIZE);
84 memcpy(journal_ptr[gindex]->buf, temp, fs->blksz); 84 memcpy(journal_ptr[gindex]->buf, temp, fs->blksz);
85 journal_ptr[gindex++]->blknr = 0; 85 journal_ptr[gindex++]->blknr = 0;
86 free(temp); 86 free(temp);
87 } else { 87 } else {
88 journal_ptr[gindex]->buf = zalloc(fs->blksz); 88 journal_ptr[gindex]->buf = zalloc(fs->blksz);
89 if (!journal_ptr[gindex]->buf) 89 if (!journal_ptr[gindex]->buf)
90 goto fail; 90 goto fail;
91 memcpy(journal_ptr[gindex]->buf, fs->sb, SUPERBLOCK_SIZE); 91 memcpy(journal_ptr[gindex]->buf, fs->sb, SUPERBLOCK_SIZE);
92 journal_ptr[gindex++]->blknr = 1; 92 journal_ptr[gindex++]->blknr = 1;
93 } 93 }
94 94
95 /* Check the file system state using journal super block */ 95 /* Check the file system state using journal super block */
96 if (ext4fs_check_journal_state(SCAN)) 96 if (ext4fs_check_journal_state(SCAN))
97 goto fail; 97 goto fail;
98 /* Check the file system state using journal super block */ 98 /* Check the file system state using journal super block */
99 if (ext4fs_check_journal_state(RECOVER)) 99 if (ext4fs_check_journal_state(RECOVER))
100 goto fail; 100 goto fail;
101 101
102 return 0; 102 return 0;
103 fail: 103 fail:
104 return -1; 104 return -1;
105 } 105 }
106 106
107 void ext4fs_dump_metadata(void) 107 void ext4fs_dump_metadata(void)
108 { 108 {
109 struct ext_filesystem *fs = get_fs(); 109 struct ext_filesystem *fs = get_fs();
110 int i; 110 int i;
111 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { 111 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
112 if (dirty_block_ptr[i]->blknr == -1) 112 if (dirty_block_ptr[i]->blknr == -1)
113 break; 113 break;
114 put_ext4((uint64_t) ((uint64_t)dirty_block_ptr[i]->blknr * 114 put_ext4((uint64_t) ((uint64_t)dirty_block_ptr[i]->blknr *
115 (uint64_t)fs->blksz), dirty_block_ptr[i]->buf, 115 (uint64_t)fs->blksz), dirty_block_ptr[i]->buf,
116 fs->blksz); 116 fs->blksz);
117 } 117 }
118 } 118 }
119 119
120 void ext4fs_free_journal(void) 120 void ext4fs_free_journal(void)
121 { 121 {
122 int i; 122 int i;
123 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { 123 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
124 if (dirty_block_ptr[i]->blknr == -1) 124 if (dirty_block_ptr[i]->blknr == -1)
125 break; 125 break;
126 if (dirty_block_ptr[i]->buf) 126 if (dirty_block_ptr[i]->buf)
127 free(dirty_block_ptr[i]->buf); 127 free(dirty_block_ptr[i]->buf);
128 } 128 }
129 129
130 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { 130 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
131 if (journal_ptr[i]->blknr == -1) 131 if (journal_ptr[i]->blknr == -1)
132 break; 132 break;
133 if (journal_ptr[i]->buf) 133 if (journal_ptr[i]->buf)
134 free(journal_ptr[i]->buf); 134 free(journal_ptr[i]->buf);
135 } 135 }
136 136
137 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { 137 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
138 if (journal_ptr[i]) 138 if (journal_ptr[i])
139 free(journal_ptr[i]); 139 free(journal_ptr[i]);
140 if (dirty_block_ptr[i]) 140 if (dirty_block_ptr[i])
141 free(dirty_block_ptr[i]); 141 free(dirty_block_ptr[i]);
142 } 142 }
143 gindex = 0; 143 gindex = 0;
144 gd_index = 0; 144 gd_index = 0;
145 jrnl_blk_idx = 1; 145 jrnl_blk_idx = 1;
146 } 146 }
147 147
148 int ext4fs_log_gdt(char *gd_table) 148 int ext4fs_log_gdt(char *gd_table)
149 { 149 {
150 struct ext_filesystem *fs = get_fs(); 150 struct ext_filesystem *fs = get_fs();
151 short i; 151 short i;
152 long int var = fs->gdtable_blkno; 152 long int var = fs->gdtable_blkno;
153 for (i = 0; i < fs->no_blk_pergdt; i++) { 153 for (i = 0; i < fs->no_blk_pergdt; i++) {
154 journal_ptr[gindex]->buf = zalloc(fs->blksz); 154 journal_ptr[gindex]->buf = zalloc(fs->blksz);
155 if (!journal_ptr[gindex]->buf) 155 if (!journal_ptr[gindex]->buf)
156 return -ENOMEM; 156 return -ENOMEM;
157 memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz); 157 memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
158 gd_table += fs->blksz; 158 gd_table += fs->blksz;
159 journal_ptr[gindex++]->blknr = var++; 159 journal_ptr[gindex++]->blknr = var++;
160 } 160 }
161 161
162 return 0; 162 return 0;
163 } 163 }
164 164
165 /* 165 /*
166 * This function stores the backup copy of meta data in RAM 166 * This function stores the backup copy of meta data in RAM
167 * journal_buffer -- Buffer containing meta data 167 * journal_buffer -- Buffer containing meta data
168 * blknr -- Block number on disk of the meta data buffer 168 * blknr -- Block number on disk of the meta data buffer
169 */ 169 */
170 int ext4fs_log_journal(char *journal_buffer, long int blknr) 170 int ext4fs_log_journal(char *journal_buffer, long int blknr)
171 { 171 {
172 struct ext_filesystem *fs = get_fs(); 172 struct ext_filesystem *fs = get_fs();
173 short i; 173 short i;
174 174
175 if (!journal_buffer) { 175 if (!journal_buffer) {
176 printf("Invalid input arguments %s\n", __func__); 176 printf("Invalid input arguments %s\n", __func__);
177 return -EINVAL; 177 return -EINVAL;
178 } 178 }
179 179
180 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { 180 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
181 if (journal_ptr[i]->blknr == -1) 181 if (journal_ptr[i]->blknr == -1)
182 break; 182 break;
183 if (journal_ptr[i]->blknr == blknr) 183 if (journal_ptr[i]->blknr == blknr)
184 return 0; 184 return 0;
185 } 185 }
186 186
187 journal_ptr[gindex]->buf = zalloc(fs->blksz); 187 journal_ptr[gindex]->buf = zalloc(fs->blksz);
188 if (!journal_ptr[gindex]->buf) 188 if (!journal_ptr[gindex]->buf)
189 return -ENOMEM; 189 return -ENOMEM;
190 190
191 memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz); 191 memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
192 journal_ptr[gindex++]->blknr = blknr; 192 journal_ptr[gindex++]->blknr = blknr;
193 193
194 return 0; 194 return 0;
195 } 195 }
196 196
197 /* 197 /*
198 * This function stores the modified meta data in RAM 198 * This function stores the modified meta data in RAM
199 * metadata_buffer -- Buffer containing meta data 199 * metadata_buffer -- Buffer containing meta data
200 * blknr -- Block number on disk of the meta data buffer 200 * blknr -- Block number on disk of the meta data buffer
201 */ 201 */
202 int ext4fs_put_metadata(char *metadata_buffer, long int blknr) 202 int ext4fs_put_metadata(char *metadata_buffer, long int blknr)
203 { 203 {
204 struct ext_filesystem *fs = get_fs(); 204 struct ext_filesystem *fs = get_fs();
205 if (!metadata_buffer) { 205 if (!metadata_buffer) {
206 printf("Invalid input arguments %s\n", __func__); 206 printf("Invalid input arguments %s\n", __func__);
207 return -EINVAL; 207 return -EINVAL;
208 } 208 }
209 dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz); 209 dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
210 if (!dirty_block_ptr[gd_index]->buf) 210 if (!dirty_block_ptr[gd_index]->buf)
211 return -ENOMEM; 211 return -ENOMEM;
212 memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz); 212 memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
213 dirty_block_ptr[gd_index++]->blknr = blknr; 213 dirty_block_ptr[gd_index++]->blknr = blknr;
214 214
215 return 0; 215 return 0;
216 } 216 }
217 217
218 void print_revoke_blks(char *revk_blk) 218 void print_revoke_blks(char *revk_blk)
219 { 219 {
220 int offset; 220 int offset;
221 int max; 221 int max;
222 long int blocknr; 222 long int blocknr;
223 struct journal_revoke_header_t *header; 223 struct journal_revoke_header_t *header;
224 224
225 if (revk_blk == NULL) 225 if (revk_blk == NULL)
226 return; 226 return;
227 227
228 header = (struct journal_revoke_header_t *) revk_blk; 228 header = (struct journal_revoke_header_t *) revk_blk;
229 offset = sizeof(struct journal_revoke_header_t); 229 offset = sizeof(struct journal_revoke_header_t);
230 max = be32_to_cpu(header->r_count); 230 max = be32_to_cpu(header->r_count);
231 printf("total bytes %d\n", max); 231 printf("total bytes %d\n", max);
232 232
233 while (offset < max) { 233 while (offset < max) {
234 blocknr = be32_to_cpu(*((long int *)(revk_blk + offset))); 234 blocknr = be32_to_cpu(*((long int *)(revk_blk + offset)));
235 printf("revoke blknr is %ld\n", blocknr); 235 printf("revoke blknr is %ld\n", blocknr);
236 offset += 4; 236 offset += 4;
237 } 237 }
238 } 238 }
239 239
240 static struct revoke_blk_list *_get_node(void) 240 static struct revoke_blk_list *_get_node(void)
241 { 241 {
242 struct revoke_blk_list *tmp_node; 242 struct revoke_blk_list *tmp_node;
243 tmp_node = zalloc(sizeof(struct revoke_blk_list)); 243 tmp_node = zalloc(sizeof(struct revoke_blk_list));
244 if (tmp_node == NULL) 244 if (tmp_node == NULL)
245 return NULL; 245 return NULL;
246 tmp_node->content = NULL; 246 tmp_node->content = NULL;
247 tmp_node->next = NULL; 247 tmp_node->next = NULL;
248 248
249 return tmp_node; 249 return tmp_node;
250 } 250 }
251 251
252 void ext4fs_push_revoke_blk(char *buffer) 252 void ext4fs_push_revoke_blk(char *buffer)
253 { 253 {
254 struct revoke_blk_list *node = NULL; 254 struct revoke_blk_list *node = NULL;
255 struct ext_filesystem *fs = get_fs(); 255 struct ext_filesystem *fs = get_fs();
256 if (buffer == NULL) { 256 if (buffer == NULL) {
257 printf("buffer ptr is NULL\n"); 257 printf("buffer ptr is NULL\n");
258 return; 258 return;
259 } 259 }
260 node = _get_node(); 260 node = _get_node();
261 if (!node) { 261 if (!node) {
262 printf("_get_node: malloc failed\n"); 262 printf("_get_node: malloc failed\n");
263 return; 263 return;
264 } 264 }
265 265
266 node->content = zalloc(fs->blksz); 266 node->content = zalloc(fs->blksz);
267 if (node->content == NULL) 267 if (node->content == NULL)
268 return; 268 return;
269 memcpy(node->content, buffer, fs->blksz); 269 memcpy(node->content, buffer, fs->blksz);
270 270
271 if (first_node == true) { 271 if (first_node == true) {
272 revk_blk_list = node; 272 revk_blk_list = node;
273 prev_node = node; 273 prev_node = node;
274 first_node = false; 274 first_node = false;
275 } else { 275 } else {
276 prev_node->next = node; 276 prev_node->next = node;
277 prev_node = node; 277 prev_node = node;
278 } 278 }
279 } 279 }
280 280
281 void ext4fs_free_revoke_blks(void) 281 void ext4fs_free_revoke_blks(void)
282 { 282 {
283 struct revoke_blk_list *tmp_node = revk_blk_list; 283 struct revoke_blk_list *tmp_node = revk_blk_list;
284 struct revoke_blk_list *next_node = NULL; 284 struct revoke_blk_list *next_node = NULL;
285 285
286 while (tmp_node != NULL) { 286 while (tmp_node != NULL) {
287 if (tmp_node->content) 287 if (tmp_node->content)
288 free(tmp_node->content); 288 free(tmp_node->content);
289 tmp_node = tmp_node->next; 289 tmp_node = tmp_node->next;
290 } 290 }
291 291
292 tmp_node = revk_blk_list; 292 tmp_node = revk_blk_list;
293 while (tmp_node != NULL) { 293 while (tmp_node != NULL) {
294 next_node = tmp_node->next; 294 next_node = tmp_node->next;
295 free(tmp_node); 295 free(tmp_node);
296 tmp_node = next_node; 296 tmp_node = next_node;
297 } 297 }
298 298
299 revk_blk_list = NULL; 299 revk_blk_list = NULL;
300 prev_node = NULL; 300 prev_node = NULL;
301 first_node = true; 301 first_node = true;
302 } 302 }
303 303
304 int check_blknr_for_revoke(long int blknr, int sequence_no) 304 int check_blknr_for_revoke(long int blknr, int sequence_no)
305 { 305 {
306 struct journal_revoke_header_t *header; 306 struct journal_revoke_header_t *header;
307 int offset; 307 int offset;
308 int max; 308 int max;
309 long int blocknr; 309 long int blocknr;
310 char *revk_blk; 310 char *revk_blk;
311 struct revoke_blk_list *tmp_revk_node = revk_blk_list; 311 struct revoke_blk_list *tmp_revk_node = revk_blk_list;
312 while (tmp_revk_node != NULL) { 312 while (tmp_revk_node != NULL) {
313 revk_blk = tmp_revk_node->content; 313 revk_blk = tmp_revk_node->content;
314 314
315 header = (struct journal_revoke_header_t *) revk_blk; 315 header = (struct journal_revoke_header_t *) revk_blk;
316 if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) { 316 if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
317 offset = sizeof(struct journal_revoke_header_t); 317 offset = sizeof(struct journal_revoke_header_t);
318 max = be32_to_cpu(header->r_count); 318 max = be32_to_cpu(header->r_count);
319 319
320 while (offset < max) { 320 while (offset < max) {
321 blocknr = be32_to_cpu(*((long int *) 321 blocknr = be32_to_cpu(*((long int *)
322 (revk_blk + offset))); 322 (revk_blk + offset)));
323 if (blocknr == blknr) 323 if (blocknr == blknr)
324 goto found; 324 goto found;
325 offset += 4; 325 offset += 4;
326 } 326 }
327 } 327 }
328 tmp_revk_node = tmp_revk_node->next; 328 tmp_revk_node = tmp_revk_node->next;
329 } 329 }
330 330
331 return -1; 331 return -1;
332 332
333 found: 333 found:
334 return 0; 334 return 0;
335 } 335 }
336 336
337 /* 337 /*
338 * This function parses the journal blocks and replays the 338 * This function parses the journal blocks and replays the
339 * suceessful transactions. A transaction is successfull 339 * suceessful transactions. A transaction is successfull
340 * if commit block is found for a descriptor block 340 * if commit block is found for a descriptor block
341 * The tags in descriptor block contain the disk block 341 * The tags in descriptor block contain the disk block
342 * numbers of the metadata to be replayed 342 * numbers of the metadata to be replayed
343 */ 343 */
344 void recover_transaction(int prev_desc_logical_no) 344 void recover_transaction(int prev_desc_logical_no)
345 { 345 {
346 struct ext2_inode inode_journal; 346 struct ext2_inode inode_journal;
347 struct ext_filesystem *fs = get_fs(); 347 struct ext_filesystem *fs = get_fs();
348 struct journal_header_t *jdb; 348 struct journal_header_t *jdb;
349 long int blknr; 349 long int blknr;
350 char *p_jdb; 350 char *p_jdb;
351 int ofs, flags; 351 int ofs, flags;
352 int i; 352 int i;
353 struct ext3_journal_block_tag *tag; 353 struct ext3_journal_block_tag *tag;
354 char *temp_buff = zalloc(fs->blksz); 354 char *temp_buff = zalloc(fs->blksz);
355 char *metadata_buff = zalloc(fs->blksz); 355 char *metadata_buff = zalloc(fs->blksz);
356 if (!temp_buff || !metadata_buff) 356 if (!temp_buff || !metadata_buff)
357 goto fail; 357 goto fail;
358 i = prev_desc_logical_no; 358 i = prev_desc_logical_no;
359 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, 359 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
360 (struct ext2_inode *)&inode_journal); 360 (struct ext2_inode *)&inode_journal);
361 blknr = read_allocated_block((struct ext2_inode *) 361 blknr = read_allocated_block((struct ext2_inode *)
362 &inode_journal, i); 362 &inode_journal, i);
363 ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, temp_buff); 363 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
364 temp_buff);
364 p_jdb = (char *)temp_buff; 365 p_jdb = (char *)temp_buff;
365 jdb = (struct journal_header_t *) temp_buff; 366 jdb = (struct journal_header_t *) temp_buff;
366 ofs = sizeof(struct journal_header_t); 367 ofs = sizeof(struct journal_header_t);
367 368
368 do { 369 do {
369 tag = (struct ext3_journal_block_tag *)&p_jdb[ofs]; 370 tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
370 ofs += sizeof(struct ext3_journal_block_tag); 371 ofs += sizeof(struct ext3_journal_block_tag);
371 372
372 if (ofs > fs->blksz) 373 if (ofs > fs->blksz)
373 break; 374 break;
374 375
375 flags = be32_to_cpu(tag->flags); 376 flags = be32_to_cpu(tag->flags);
376 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID)) 377 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
377 ofs += 16; 378 ofs += 16;
378 379
379 i++; 380 i++;
380 debug("\t\ttag %u\n", be32_to_cpu(tag->block)); 381 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
381 if (revk_blk_list != NULL) { 382 if (revk_blk_list != NULL) {
382 if (check_blknr_for_revoke(be32_to_cpu(tag->block), 383 if (check_blknr_for_revoke(be32_to_cpu(tag->block),
383 be32_to_cpu(jdb->h_sequence)) == 0) 384 be32_to_cpu(jdb->h_sequence)) == 0)
384 continue; 385 continue;
385 } 386 }
386 blknr = read_allocated_block(&inode_journal, i); 387 blknr = read_allocated_block(&inode_journal, i);
387 ext4fs_devread(blknr * fs->sect_perblk, 0, 388 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
388 fs->blksz, metadata_buff); 389 fs->blksz, metadata_buff);
389 put_ext4((uint64_t)(be32_to_cpu(tag->block) * fs->blksz), 390 put_ext4((uint64_t)(be32_to_cpu(tag->block) * fs->blksz),
390 metadata_buff, (uint32_t) fs->blksz); 391 metadata_buff, (uint32_t) fs->blksz);
391 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG)); 392 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
392 fail: 393 fail:
393 free(temp_buff); 394 free(temp_buff);
394 free(metadata_buff); 395 free(metadata_buff);
395 } 396 }
396 397
397 void print_jrnl_status(int recovery_flag) 398 void print_jrnl_status(int recovery_flag)
398 { 399 {
399 if (recovery_flag == RECOVER) 400 if (recovery_flag == RECOVER)
400 printf("Journal Recovery Completed\n"); 401 printf("Journal Recovery Completed\n");
401 else 402 else
402 printf("Journal Scan Completed\n"); 403 printf("Journal Scan Completed\n");
403 } 404 }
404 405
405 int ext4fs_check_journal_state(int recovery_flag) 406 int ext4fs_check_journal_state(int recovery_flag)
406 { 407 {
407 int i; 408 int i;
408 int DB_FOUND = NO; 409 int DB_FOUND = NO;
409 long int blknr; 410 long int blknr;
410 int transaction_state = TRANSACTION_COMPLETE; 411 int transaction_state = TRANSACTION_COMPLETE;
411 int prev_desc_logical_no = 0; 412 int prev_desc_logical_no = 0;
412 int curr_desc_logical_no = 0; 413 int curr_desc_logical_no = 0;
413 int ofs, flags; 414 int ofs, flags;
414 struct ext2_inode inode_journal; 415 struct ext2_inode inode_journal;
415 struct journal_superblock_t *jsb = NULL; 416 struct journal_superblock_t *jsb = NULL;
416 struct journal_header_t *jdb = NULL; 417 struct journal_header_t *jdb = NULL;
417 char *p_jdb = NULL; 418 char *p_jdb = NULL;
418 struct ext3_journal_block_tag *tag = NULL; 419 struct ext3_journal_block_tag *tag = NULL;
419 char *temp_buff = NULL; 420 char *temp_buff = NULL;
420 char *temp_buff1 = NULL; 421 char *temp_buff1 = NULL;
421 struct ext_filesystem *fs = get_fs(); 422 struct ext_filesystem *fs = get_fs();
422 423
423 temp_buff = zalloc(fs->blksz); 424 temp_buff = zalloc(fs->blksz);
424 if (!temp_buff) 425 if (!temp_buff)
425 return -ENOMEM; 426 return -ENOMEM;
426 temp_buff1 = zalloc(fs->blksz); 427 temp_buff1 = zalloc(fs->blksz);
427 if (!temp_buff1) { 428 if (!temp_buff1) {
428 free(temp_buff); 429 free(temp_buff);
429 return -ENOMEM; 430 return -ENOMEM;
430 } 431 }
431 432
432 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); 433 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
433 blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK); 434 blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
434 ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, temp_buff); 435 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
436 temp_buff);
435 jsb = (struct journal_superblock_t *) temp_buff; 437 jsb = (struct journal_superblock_t *) temp_buff;
436 438
437 if (fs->sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) { 439 if (fs->sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
438 if (recovery_flag == RECOVER) 440 if (recovery_flag == RECOVER)
439 printf("Recovery required\n"); 441 printf("Recovery required\n");
440 } else { 442 } else {
441 if (recovery_flag == RECOVER) 443 if (recovery_flag == RECOVER)
442 printf("File System is consistent\n"); 444 printf("File System is consistent\n");
443 goto end; 445 goto end;
444 } 446 }
445 447
446 if (be32_to_cpu(jsb->s_start) == 0) 448 if (be32_to_cpu(jsb->s_start) == 0)
447 goto end; 449 goto end;
448 450
449 if (!(jsb->s_feature_compat & 451 if (!(jsb->s_feature_compat &
450 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM))) 452 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
451 jsb->s_feature_compat |= 453 jsb->s_feature_compat |=
452 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); 454 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
453 455
454 i = be32_to_cpu(jsb->s_first); 456 i = be32_to_cpu(jsb->s_first);
455 while (1) { 457 while (1) {
456 blknr = read_allocated_block(&inode_journal, i); 458 blknr = read_allocated_block(&inode_journal, i);
457 memset(temp_buff1, '\0', fs->blksz); 459 memset(temp_buff1, '\0', fs->blksz);
458 ext4fs_devread(blknr * fs->sect_perblk, 460 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
459 0, fs->blksz, temp_buff1); 461 0, fs->blksz, temp_buff1);
460 jdb = (struct journal_header_t *) temp_buff1; 462 jdb = (struct journal_header_t *) temp_buff1;
461 463
462 if (be32_to_cpu(jdb->h_blocktype) == 464 if (be32_to_cpu(jdb->h_blocktype) ==
463 EXT3_JOURNAL_DESCRIPTOR_BLOCK) { 465 EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
464 if (be32_to_cpu(jdb->h_sequence) != 466 if (be32_to_cpu(jdb->h_sequence) !=
465 be32_to_cpu(jsb->s_sequence)) { 467 be32_to_cpu(jsb->s_sequence)) {
466 print_jrnl_status(recovery_flag); 468 print_jrnl_status(recovery_flag);
467 break; 469 break;
468 } 470 }
469 471
470 curr_desc_logical_no = i; 472 curr_desc_logical_no = i;
471 if (transaction_state == TRANSACTION_COMPLETE) 473 if (transaction_state == TRANSACTION_COMPLETE)
472 transaction_state = TRANSACTION_RUNNING; 474 transaction_state = TRANSACTION_RUNNING;
473 else 475 else
474 return -1; 476 return -1;
475 p_jdb = (char *)temp_buff1; 477 p_jdb = (char *)temp_buff1;
476 ofs = sizeof(struct journal_header_t); 478 ofs = sizeof(struct journal_header_t);
477 do { 479 do {
478 tag = (struct ext3_journal_block_tag *) 480 tag = (struct ext3_journal_block_tag *)
479 &p_jdb[ofs]; 481 &p_jdb[ofs];
480 ofs += sizeof(struct ext3_journal_block_tag); 482 ofs += sizeof(struct ext3_journal_block_tag);
481 if (ofs > fs->blksz) 483 if (ofs > fs->blksz)
482 break; 484 break;
483 flags = be32_to_cpu(tag->flags); 485 flags = be32_to_cpu(tag->flags);
484 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID)) 486 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
485 ofs += 16; 487 ofs += 16;
486 i++; 488 i++;
487 debug("\t\ttag %u\n", be32_to_cpu(tag->block)); 489 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
488 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG)); 490 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
489 i++; 491 i++;
490 DB_FOUND = YES; 492 DB_FOUND = YES;
491 } else if (be32_to_cpu(jdb->h_blocktype) == 493 } else if (be32_to_cpu(jdb->h_blocktype) ==
492 EXT3_JOURNAL_COMMIT_BLOCK) { 494 EXT3_JOURNAL_COMMIT_BLOCK) {
493 if (be32_to_cpu(jdb->h_sequence) != 495 if (be32_to_cpu(jdb->h_sequence) !=
494 be32_to_cpu(jsb->s_sequence)) { 496 be32_to_cpu(jsb->s_sequence)) {
495 print_jrnl_status(recovery_flag); 497 print_jrnl_status(recovery_flag);
496 break; 498 break;
497 } 499 }
498 500
499 if (transaction_state == TRANSACTION_RUNNING || 501 if (transaction_state == TRANSACTION_RUNNING ||
500 (DB_FOUND == NO)) { 502 (DB_FOUND == NO)) {
501 transaction_state = TRANSACTION_COMPLETE; 503 transaction_state = TRANSACTION_COMPLETE;
502 i++; 504 i++;
503 jsb->s_sequence = 505 jsb->s_sequence =
504 cpu_to_be32(be32_to_cpu( 506 cpu_to_be32(be32_to_cpu(
505 jsb->s_sequence) + 1); 507 jsb->s_sequence) + 1);
506 } 508 }
507 prev_desc_logical_no = curr_desc_logical_no; 509 prev_desc_logical_no = curr_desc_logical_no;
508 if ((recovery_flag == RECOVER) && (DB_FOUND == YES)) 510 if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
509 recover_transaction(prev_desc_logical_no); 511 recover_transaction(prev_desc_logical_no);
510 512
511 DB_FOUND = NO; 513 DB_FOUND = NO;
512 } else if (be32_to_cpu(jdb->h_blocktype) == 514 } else if (be32_to_cpu(jdb->h_blocktype) ==
513 EXT3_JOURNAL_REVOKE_BLOCK) { 515 EXT3_JOURNAL_REVOKE_BLOCK) {
514 if (be32_to_cpu(jdb->h_sequence) != 516 if (be32_to_cpu(jdb->h_sequence) !=
515 be32_to_cpu(jsb->s_sequence)) { 517 be32_to_cpu(jsb->s_sequence)) {
516 print_jrnl_status(recovery_flag); 518 print_jrnl_status(recovery_flag);
517 break; 519 break;
518 } 520 }
519 if (recovery_flag == SCAN) 521 if (recovery_flag == SCAN)
520 ext4fs_push_revoke_blk((char *)jdb); 522 ext4fs_push_revoke_blk((char *)jdb);
521 i++; 523 i++;
522 } else { 524 } else {
523 debug("Else Case\n"); 525 debug("Else Case\n");
524 if (be32_to_cpu(jdb->h_sequence) != 526 if (be32_to_cpu(jdb->h_sequence) !=
525 be32_to_cpu(jsb->s_sequence)) { 527 be32_to_cpu(jsb->s_sequence)) {
526 print_jrnl_status(recovery_flag); 528 print_jrnl_status(recovery_flag);
527 break; 529 break;
528 } 530 }
529 } 531 }
530 } 532 }
531 533
532 end: 534 end:
533 if (recovery_flag == RECOVER) { 535 if (recovery_flag == RECOVER) {
534 jsb->s_start = cpu_to_be32(1); 536 jsb->s_start = cpu_to_be32(1);
535 jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1); 537 jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
536 /* get the superblock */ 538 /* get the superblock */
537 ext4_read_superblock((char *)fs->sb); 539 ext4_read_superblock((char *)fs->sb);
538 fs->sb->feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER; 540 fs->sb->feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
539 541
540 /* Update the super block */ 542 /* Update the super block */
541 put_ext4((uint64_t) (SUPERBLOCK_SIZE), 543 put_ext4((uint64_t) (SUPERBLOCK_SIZE),
542 (struct ext2_sblock *)fs->sb, 544 (struct ext2_sblock *)fs->sb,
543 (uint32_t) SUPERBLOCK_SIZE); 545 (uint32_t) SUPERBLOCK_SIZE);
544 ext4_read_superblock((char *)fs->sb); 546 ext4_read_superblock((char *)fs->sb);
545 547
546 blknr = read_allocated_block(&inode_journal, 548 blknr = read_allocated_block(&inode_journal,
547 EXT2_JOURNAL_SUPERBLOCK); 549 EXT2_JOURNAL_SUPERBLOCK);
548 put_ext4((uint64_t) (blknr * fs->blksz), 550 put_ext4((uint64_t) (blknr * fs->blksz),
549 (struct journal_superblock_t *)temp_buff, 551 (struct journal_superblock_t *)temp_buff,
550 (uint32_t) fs->blksz); 552 (uint32_t) fs->blksz);
551 ext4fs_free_revoke_blks(); 553 ext4fs_free_revoke_blks();
552 } 554 }
553 free(temp_buff); 555 free(temp_buff);
554 free(temp_buff1); 556 free(temp_buff1);
555 557
556 return 0; 558 return 0;
557 } 559 }
558 560
559 static void update_descriptor_block(long int blknr) 561 static void update_descriptor_block(long int blknr)
560 { 562 {
561 int i; 563 int i;
562 long int jsb_blknr; 564 long int jsb_blknr;
563 struct journal_header_t jdb; 565 struct journal_header_t jdb;
564 struct ext3_journal_block_tag tag; 566 struct ext3_journal_block_tag tag;
565 struct ext2_inode inode_journal; 567 struct ext2_inode inode_journal;
566 struct journal_superblock_t *jsb = NULL; 568 struct journal_superblock_t *jsb = NULL;
567 char *buf = NULL; 569 char *buf = NULL;
568 char *temp = NULL; 570 char *temp = NULL;
569 struct ext_filesystem *fs = get_fs(); 571 struct ext_filesystem *fs = get_fs();
570 char *temp_buff = zalloc(fs->blksz); 572 char *temp_buff = zalloc(fs->blksz);
571 if (!temp_buff) 573 if (!temp_buff)
572 return; 574 return;
573 575
574 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); 576 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
575 jsb_blknr = read_allocated_block(&inode_journal, 577 jsb_blknr = read_allocated_block(&inode_journal,
576 EXT2_JOURNAL_SUPERBLOCK); 578 EXT2_JOURNAL_SUPERBLOCK);
577 ext4fs_devread(jsb_blknr * fs->sect_perblk, 0, fs->blksz, temp_buff); 579 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
580 temp_buff);
578 jsb = (struct journal_superblock_t *) temp_buff; 581 jsb = (struct journal_superblock_t *) temp_buff;
579 582
580 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK); 583 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
581 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER); 584 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
582 jdb.h_sequence = jsb->s_sequence; 585 jdb.h_sequence = jsb->s_sequence;
583 buf = zalloc(fs->blksz); 586 buf = zalloc(fs->blksz);
584 if (!buf) { 587 if (!buf) {
585 free(temp_buff); 588 free(temp_buff);
586 return; 589 return;
587 } 590 }
588 temp = buf; 591 temp = buf;
589 memcpy(buf, &jdb, sizeof(struct journal_header_t)); 592 memcpy(buf, &jdb, sizeof(struct journal_header_t));
590 temp += sizeof(struct journal_header_t); 593 temp += sizeof(struct journal_header_t);
591 594
592 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { 595 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
593 if (journal_ptr[i]->blknr == -1) 596 if (journal_ptr[i]->blknr == -1)
594 break; 597 break;
595 598
596 tag.block = cpu_to_be32(journal_ptr[i]->blknr); 599 tag.block = cpu_to_be32(journal_ptr[i]->blknr);
597 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID); 600 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
598 memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag)); 601 memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
599 temp = temp + sizeof(struct ext3_journal_block_tag); 602 temp = temp + sizeof(struct ext3_journal_block_tag);
600 } 603 }
601 604
602 tag.block = cpu_to_be32(journal_ptr[--i]->blknr); 605 tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
603 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG); 606 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
604 memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag, 607 memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
605 sizeof(struct ext3_journal_block_tag)); 608 sizeof(struct ext3_journal_block_tag));
606 put_ext4((uint64_t) (blknr * fs->blksz), buf, (uint32_t) fs->blksz); 609 put_ext4((uint64_t) (blknr * fs->blksz), buf, (uint32_t) fs->blksz);
607 610
608 free(temp_buff); 611 free(temp_buff);
609 free(buf); 612 free(buf);
610 } 613 }
611 614
612 static void update_commit_block(long int blknr) 615 static void update_commit_block(long int blknr)
613 { 616 {
614 struct journal_header_t jdb; 617 struct journal_header_t jdb;
615 struct ext_filesystem *fs = get_fs(); 618 struct ext_filesystem *fs = get_fs();
616 char *buf = NULL; 619 char *buf = NULL;
617 struct ext2_inode inode_journal; 620 struct ext2_inode inode_journal;
618 struct journal_superblock_t *jsb; 621 struct journal_superblock_t *jsb;
619 long int jsb_blknr; 622 long int jsb_blknr;
620 char *temp_buff = zalloc(fs->blksz); 623 char *temp_buff = zalloc(fs->blksz);
621 if (!temp_buff) 624 if (!temp_buff)
622 return; 625 return;
623 626
624 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); 627 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
628 &inode_journal);
625 jsb_blknr = read_allocated_block(&inode_journal, 629 jsb_blknr = read_allocated_block(&inode_journal,
626 EXT2_JOURNAL_SUPERBLOCK); 630 EXT2_JOURNAL_SUPERBLOCK);
627 ext4fs_devread(jsb_blknr * fs->sect_perblk, 0, fs->blksz, temp_buff); 631 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
632 temp_buff);
628 jsb = (struct journal_superblock_t *) temp_buff; 633 jsb = (struct journal_superblock_t *) temp_buff;
629 634
630 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK); 635 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
631 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER); 636 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
632 jdb.h_sequence = jsb->s_sequence; 637 jdb.h_sequence = jsb->s_sequence;
633 buf = zalloc(fs->blksz); 638 buf = zalloc(fs->blksz);
634 if (!buf) { 639 if (!buf) {
635 free(temp_buff); 640 free(temp_buff);
636 return; 641 return;
637 } 642 }
638 memcpy(buf, &jdb, sizeof(struct journal_header_t)); 643 memcpy(buf, &jdb, sizeof(struct journal_header_t));
639 put_ext4((uint64_t) (blknr * fs->blksz), buf, (uint32_t) fs->blksz); 644 put_ext4((uint64_t) (blknr * fs->blksz), buf, (uint32_t) fs->blksz);
640 645
641 free(temp_buff); 646 free(temp_buff);
642 free(buf); 647 free(buf);
643 } 648 }
644 649
645 void ext4fs_update_journal(void) 650 void ext4fs_update_journal(void)
646 { 651 {
647 struct ext2_inode inode_journal; 652 struct ext2_inode inode_journal;
648 struct ext_filesystem *fs = get_fs(); 653 struct ext_filesystem *fs = get_fs();
649 long int blknr; 654 long int blknr;
650 int i; 655 int i;
651 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); 656 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
652 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); 657 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
653 update_descriptor_block(blknr); 658 update_descriptor_block(blknr);
654 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { 659 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
655 if (journal_ptr[i]->blknr == -1) 660 if (journal_ptr[i]->blknr == -1)
656 break; 661 break;
657 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); 662 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
658 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), 663 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
659 journal_ptr[i]->buf, fs->blksz); 664 journal_ptr[i]->buf, fs->blksz);
660 } 665 }
661 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); 666 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
662 update_commit_block(blknr); 667 update_commit_block(blknr);
663 printf("update journal finished\n"); 668 printf("update journal finished\n");
664 } 669 }
665 670
fs/ext4/ext4_write.c
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * ext4ls and ext4load : Based on ext2 ls and load support in Uboot. 7 * ext4ls and ext4load : Based on ext2 ls and load support in Uboot.
8 * Ext4 read optimization taken from Open-Moko 8 * Ext4 read optimization taken from Open-Moko
9 * Qi bootloader 9 * Qi bootloader
10 * 10 *
11 * (C) Copyright 2004 11 * (C) Copyright 2004
12 * esd gmbh <www.esd-electronics.com> 12 * esd gmbh <www.esd-electronics.com>
13 * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 13 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
14 * 14 *
15 * based on code from grub2 fs/ext2.c and fs/fshelp.c by 15 * based on code from grub2 fs/ext2.c and fs/fshelp.c by
16 * GRUB -- GRand Unified Bootloader 16 * GRUB -- GRand Unified Bootloader
17 * Copyright (C) 2003, 2004 Free Software Foundation, Inc. 17 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
18 * 18 *
19 * ext4write : Based on generic ext4 protocol. 19 * ext4write : Based on generic ext4 protocol.
20 * 20 *
21 * This program is free software; you can redistribute it and/or modify 21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by 22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or 23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version. 24 * (at your option) any later version.
25 * 25 *
26 * This program is distributed in the hope that it will be useful, 26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details. 29 * GNU General Public License for more details.
30 * 30 *
31 * You should have received a copy of the GNU General Public License 31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software 32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 33 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 */ 34 */
35 35
36 36
37 #include <common.h> 37 #include <common.h>
38 #include <linux/stat.h> 38 #include <linux/stat.h>
39 #include <div64.h> 39 #include <div64.h>
40 #include "ext4_common.h" 40 #include "ext4_common.h"
41 41
42 static void ext4fs_update(void) 42 static void ext4fs_update(void)
43 { 43 {
44 short i; 44 short i;
45 ext4fs_update_journal(); 45 ext4fs_update_journal();
46 struct ext_filesystem *fs = get_fs(); 46 struct ext_filesystem *fs = get_fs();
47 47
48 /* update super block */ 48 /* update super block */
49 put_ext4((uint64_t)(SUPERBLOCK_SIZE), 49 put_ext4((uint64_t)(SUPERBLOCK_SIZE),
50 (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE); 50 (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE);
51 51
52 /* update block groups */ 52 /* update block groups */
53 for (i = 0; i < fs->no_blkgrp; i++) { 53 for (i = 0; i < fs->no_blkgrp; i++) {
54 fs->bgd[i].bg_checksum = ext4fs_checksum_update(i); 54 fs->bgd[i].bg_checksum = ext4fs_checksum_update(i);
55 put_ext4((uint64_t)(fs->bgd[i].block_id * fs->blksz), 55 put_ext4((uint64_t)(fs->bgd[i].block_id * fs->blksz),
56 fs->blk_bmaps[i], fs->blksz); 56 fs->blk_bmaps[i], fs->blksz);
57 } 57 }
58 58
59 /* update inode table groups */ 59 /* update inode table groups */
60 for (i = 0; i < fs->no_blkgrp; i++) { 60 for (i = 0; i < fs->no_blkgrp; i++) {
61 put_ext4((uint64_t) (fs->bgd[i].inode_id * fs->blksz), 61 put_ext4((uint64_t) (fs->bgd[i].inode_id * fs->blksz),
62 fs->inode_bmaps[i], fs->blksz); 62 fs->inode_bmaps[i], fs->blksz);
63 } 63 }
64 64
65 /* update the block group descriptor table */ 65 /* update the block group descriptor table */
66 put_ext4((uint64_t)(fs->gdtable_blkno * fs->blksz), 66 put_ext4((uint64_t)(fs->gdtable_blkno * fs->blksz),
67 (struct ext2_block_group *)fs->gdtable, 67 (struct ext2_block_group *)fs->gdtable,
68 (fs->blksz * fs->no_blk_pergdt)); 68 (fs->blksz * fs->no_blk_pergdt));
69 69
70 ext4fs_dump_metadata(); 70 ext4fs_dump_metadata();
71 71
72 gindex = 0; 72 gindex = 0;
73 gd_index = 0; 73 gd_index = 0;
74 } 74 }
75 75
76 int ext4fs_get_bgdtable(void) 76 int ext4fs_get_bgdtable(void)
77 { 77 {
78 int status; 78 int status;
79 int grp_desc_size; 79 int grp_desc_size;
80 struct ext_filesystem *fs = get_fs(); 80 struct ext_filesystem *fs = get_fs();
81 grp_desc_size = sizeof(struct ext2_block_group); 81 grp_desc_size = sizeof(struct ext2_block_group);
82 fs->no_blk_pergdt = (fs->no_blkgrp * grp_desc_size) / fs->blksz; 82 fs->no_blk_pergdt = (fs->no_blkgrp * grp_desc_size) / fs->blksz;
83 if ((fs->no_blkgrp * grp_desc_size) % fs->blksz) 83 if ((fs->no_blkgrp * grp_desc_size) % fs->blksz)
84 fs->no_blk_pergdt++; 84 fs->no_blk_pergdt++;
85 85
86 /* allocate memory for gdtable */ 86 /* allocate memory for gdtable */
87 fs->gdtable = zalloc(fs->blksz * fs->no_blk_pergdt); 87 fs->gdtable = zalloc(fs->blksz * fs->no_blk_pergdt);
88 if (!fs->gdtable) 88 if (!fs->gdtable)
89 return -ENOMEM; 89 return -ENOMEM;
90 /* read the group descriptor table */ 90 /* read the group descriptor table */
91 status = ext4fs_devread(fs->gdtable_blkno * fs->sect_perblk, 0, 91 status = ext4fs_devread((lbaint_t)fs->gdtable_blkno * fs->sect_perblk,
92 fs->blksz * fs->no_blk_pergdt, fs->gdtable); 92 0, fs->blksz * fs->no_blk_pergdt, fs->gdtable);
93 if (status == 0) 93 if (status == 0)
94 goto fail; 94 goto fail;
95 95
96 if (ext4fs_log_gdt(fs->gdtable)) { 96 if (ext4fs_log_gdt(fs->gdtable)) {
97 printf("Error in ext4fs_log_gdt\n"); 97 printf("Error in ext4fs_log_gdt\n");
98 return -1; 98 return -1;
99 } 99 }
100 100
101 return 0; 101 return 0;
102 fail: 102 fail:
103 free(fs->gdtable); 103 free(fs->gdtable);
104 fs->gdtable = NULL; 104 fs->gdtable = NULL;
105 105
106 return -1; 106 return -1;
107 } 107 }
108 108
109 static void delete_single_indirect_block(struct ext2_inode *inode) 109 static void delete_single_indirect_block(struct ext2_inode *inode)
110 { 110 {
111 struct ext2_block_group *bgd = NULL; 111 struct ext2_block_group *bgd = NULL;
112 static int prev_bg_bmap_idx = -1; 112 static int prev_bg_bmap_idx = -1;
113 long int blknr; 113 long int blknr;
114 int remainder; 114 int remainder;
115 int bg_idx; 115 int bg_idx;
116 int status; 116 int status;
117 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 117 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
118 struct ext_filesystem *fs = get_fs(); 118 struct ext_filesystem *fs = get_fs();
119 char *journal_buffer = zalloc(fs->blksz); 119 char *journal_buffer = zalloc(fs->blksz);
120 if (!journal_buffer) { 120 if (!journal_buffer) {
121 printf("No memory\n"); 121 printf("No memory\n");
122 return; 122 return;
123 } 123 }
124 /* get block group descriptor table */ 124 /* get block group descriptor table */
125 bgd = (struct ext2_block_group *)fs->gdtable; 125 bgd = (struct ext2_block_group *)fs->gdtable;
126 126
127 /* deleting the single indirect block associated with inode */ 127 /* deleting the single indirect block associated with inode */
128 if (inode->b.blocks.indir_block != 0) { 128 if (inode->b.blocks.indir_block != 0) {
129 debug("SIPB releasing %u\n", inode->b.blocks.indir_block); 129 debug("SIPB releasing %u\n", inode->b.blocks.indir_block);
130 blknr = inode->b.blocks.indir_block; 130 blknr = inode->b.blocks.indir_block;
131 if (fs->blksz != 1024) { 131 if (fs->blksz != 1024) {
132 bg_idx = blknr / blk_per_grp; 132 bg_idx = blknr / blk_per_grp;
133 } else { 133 } else {
134 bg_idx = blknr / blk_per_grp; 134 bg_idx = blknr / blk_per_grp;
135 remainder = blknr % blk_per_grp; 135 remainder = blknr % blk_per_grp;
136 if (!remainder) 136 if (!remainder)
137 bg_idx--; 137 bg_idx--;
138 } 138 }
139 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); 139 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
140 bgd[bg_idx].free_blocks++; 140 bgd[bg_idx].free_blocks++;
141 fs->sb->free_blocks++; 141 fs->sb->free_blocks++;
142 /* journal backup */ 142 /* journal backup */
143 if (prev_bg_bmap_idx != bg_idx) { 143 if (prev_bg_bmap_idx != bg_idx) {
144 status = 144 status =
145 ext4fs_devread(bgd[bg_idx].block_id * 145 ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
146 fs->sect_perblk, 0, fs->blksz, 146 fs->sect_perblk, 0, fs->blksz,
147 journal_buffer); 147 journal_buffer);
148 if (status == 0) 148 if (status == 0)
149 goto fail; 149 goto fail;
150 if (ext4fs_log_journal 150 if (ext4fs_log_journal
151 (journal_buffer, bgd[bg_idx].block_id)) 151 (journal_buffer, bgd[bg_idx].block_id))
152 goto fail; 152 goto fail;
153 prev_bg_bmap_idx = bg_idx; 153 prev_bg_bmap_idx = bg_idx;
154 } 154 }
155 } 155 }
156 fail: 156 fail:
157 free(journal_buffer); 157 free(journal_buffer);
158 } 158 }
159 159
160 static void delete_double_indirect_block(struct ext2_inode *inode) 160 static void delete_double_indirect_block(struct ext2_inode *inode)
161 { 161 {
162 int i; 162 int i;
163 short status; 163 short status;
164 static int prev_bg_bmap_idx = -1; 164 static int prev_bg_bmap_idx = -1;
165 long int blknr; 165 long int blknr;
166 int remainder; 166 int remainder;
167 int bg_idx; 167 int bg_idx;
168 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 168 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
169 unsigned int *di_buffer = NULL; 169 unsigned int *di_buffer = NULL;
170 unsigned int *DIB_start_addr = NULL; 170 unsigned int *DIB_start_addr = NULL;
171 struct ext2_block_group *bgd = NULL; 171 struct ext2_block_group *bgd = NULL;
172 struct ext_filesystem *fs = get_fs(); 172 struct ext_filesystem *fs = get_fs();
173 char *journal_buffer = zalloc(fs->blksz); 173 char *journal_buffer = zalloc(fs->blksz);
174 if (!journal_buffer) { 174 if (!journal_buffer) {
175 printf("No memory\n"); 175 printf("No memory\n");
176 return; 176 return;
177 } 177 }
178 /* get the block group descriptor table */ 178 /* get the block group descriptor table */
179 bgd = (struct ext2_block_group *)fs->gdtable; 179 bgd = (struct ext2_block_group *)fs->gdtable;
180 180
181 if (inode->b.blocks.double_indir_block != 0) { 181 if (inode->b.blocks.double_indir_block != 0) {
182 di_buffer = zalloc(fs->blksz); 182 di_buffer = zalloc(fs->blksz);
183 if (!di_buffer) { 183 if (!di_buffer) {
184 printf("No memory\n"); 184 printf("No memory\n");
185 return; 185 return;
186 } 186 }
187 DIB_start_addr = (unsigned int *)di_buffer; 187 DIB_start_addr = (unsigned int *)di_buffer;
188 blknr = inode->b.blocks.double_indir_block; 188 blknr = inode->b.blocks.double_indir_block;
189 status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, 189 status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
190 (char *)di_buffer); 190 fs->blksz, (char *)di_buffer);
191 for (i = 0; i < fs->blksz / sizeof(int); i++) { 191 for (i = 0; i < fs->blksz / sizeof(int); i++) {
192 if (*di_buffer == 0) 192 if (*di_buffer == 0)
193 break; 193 break;
194 194
195 debug("DICB releasing %u\n", *di_buffer); 195 debug("DICB releasing %u\n", *di_buffer);
196 if (fs->blksz != 1024) { 196 if (fs->blksz != 1024) {
197 bg_idx = (*di_buffer) / blk_per_grp; 197 bg_idx = (*di_buffer) / blk_per_grp;
198 } else { 198 } else {
199 bg_idx = (*di_buffer) / blk_per_grp; 199 bg_idx = (*di_buffer) / blk_per_grp;
200 remainder = (*di_buffer) % blk_per_grp; 200 remainder = (*di_buffer) % blk_per_grp;
201 if (!remainder) 201 if (!remainder)
202 bg_idx--; 202 bg_idx--;
203 } 203 }
204 ext4fs_reset_block_bmap(*di_buffer, 204 ext4fs_reset_block_bmap(*di_buffer,
205 fs->blk_bmaps[bg_idx], bg_idx); 205 fs->blk_bmaps[bg_idx], bg_idx);
206 di_buffer++; 206 di_buffer++;
207 bgd[bg_idx].free_blocks++; 207 bgd[bg_idx].free_blocks++;
208 fs->sb->free_blocks++; 208 fs->sb->free_blocks++;
209 /* journal backup */ 209 /* journal backup */
210 if (prev_bg_bmap_idx != bg_idx) { 210 if (prev_bg_bmap_idx != bg_idx) {
211 status = ext4fs_devread(bgd[bg_idx].block_id 211 status = ext4fs_devread((lbaint_t)
212 bgd[bg_idx].block_id
212 * fs->sect_perblk, 0, 213 * fs->sect_perblk, 0,
213 fs->blksz, 214 fs->blksz,
214 journal_buffer); 215 journal_buffer);
215 if (status == 0) 216 if (status == 0)
216 goto fail; 217 goto fail;
217 218
218 if (ext4fs_log_journal(journal_buffer, 219 if (ext4fs_log_journal(journal_buffer,
219 bgd[bg_idx].block_id)) 220 bgd[bg_idx].block_id))
220 goto fail; 221 goto fail;
221 prev_bg_bmap_idx = bg_idx; 222 prev_bg_bmap_idx = bg_idx;
222 } 223 }
223 } 224 }
224 225
225 /* removing the parent double indirect block */ 226 /* removing the parent double indirect block */
226 blknr = inode->b.blocks.double_indir_block; 227 blknr = inode->b.blocks.double_indir_block;
227 if (fs->blksz != 1024) { 228 if (fs->blksz != 1024) {
228 bg_idx = blknr / blk_per_grp; 229 bg_idx = blknr / blk_per_grp;
229 } else { 230 } else {
230 bg_idx = blknr / blk_per_grp; 231 bg_idx = blknr / blk_per_grp;
231 remainder = blknr % blk_per_grp; 232 remainder = blknr % blk_per_grp;
232 if (!remainder) 233 if (!remainder)
233 bg_idx--; 234 bg_idx--;
234 } 235 }
235 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); 236 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
236 bgd[bg_idx].free_blocks++; 237 bgd[bg_idx].free_blocks++;
237 fs->sb->free_blocks++; 238 fs->sb->free_blocks++;
238 /* journal backup */ 239 /* journal backup */
239 if (prev_bg_bmap_idx != bg_idx) { 240 if (prev_bg_bmap_idx != bg_idx) {
240 memset(journal_buffer, '\0', fs->blksz); 241 memset(journal_buffer, '\0', fs->blksz);
241 status = ext4fs_devread(bgd[bg_idx].block_id * 242 status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
242 fs->sect_perblk, 0, fs->blksz, 243 fs->sect_perblk, 0, fs->blksz,
243 journal_buffer); 244 journal_buffer);
244 if (status == 0) 245 if (status == 0)
245 goto fail; 246 goto fail;
246 247
247 if (ext4fs_log_journal(journal_buffer, 248 if (ext4fs_log_journal(journal_buffer,
248 bgd[bg_idx].block_id)) 249 bgd[bg_idx].block_id))
249 goto fail; 250 goto fail;
250 prev_bg_bmap_idx = bg_idx; 251 prev_bg_bmap_idx = bg_idx;
251 } 252 }
252 debug("DIPB releasing %ld\n", blknr); 253 debug("DIPB releasing %ld\n", blknr);
253 } 254 }
254 fail: 255 fail:
255 free(DIB_start_addr); 256 free(DIB_start_addr);
256 free(journal_buffer); 257 free(journal_buffer);
257 } 258 }
258 259
259 static void delete_triple_indirect_block(struct ext2_inode *inode) 260 static void delete_triple_indirect_block(struct ext2_inode *inode)
260 { 261 {
261 int i, j; 262 int i, j;
262 short status; 263 short status;
263 static int prev_bg_bmap_idx = -1; 264 static int prev_bg_bmap_idx = -1;
264 long int blknr; 265 long int blknr;
265 int remainder; 266 int remainder;
266 int bg_idx; 267 int bg_idx;
267 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 268 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
268 unsigned int *tigp_buffer = NULL; 269 unsigned int *tigp_buffer = NULL;
269 unsigned int *tib_start_addr = NULL; 270 unsigned int *tib_start_addr = NULL;
270 unsigned int *tip_buffer = NULL; 271 unsigned int *tip_buffer = NULL;
271 unsigned int *tipb_start_addr = NULL; 272 unsigned int *tipb_start_addr = NULL;
272 struct ext2_block_group *bgd = NULL; 273 struct ext2_block_group *bgd = NULL;
273 struct ext_filesystem *fs = get_fs(); 274 struct ext_filesystem *fs = get_fs();
274 char *journal_buffer = zalloc(fs->blksz); 275 char *journal_buffer = zalloc(fs->blksz);
275 if (!journal_buffer) { 276 if (!journal_buffer) {
276 printf("No memory\n"); 277 printf("No memory\n");
277 return; 278 return;
278 } 279 }
279 /* get block group descriptor table */ 280 /* get block group descriptor table */
280 bgd = (struct ext2_block_group *)fs->gdtable; 281 bgd = (struct ext2_block_group *)fs->gdtable;
281 282
282 if (inode->b.blocks.triple_indir_block != 0) { 283 if (inode->b.blocks.triple_indir_block != 0) {
283 tigp_buffer = zalloc(fs->blksz); 284 tigp_buffer = zalloc(fs->blksz);
284 if (!tigp_buffer) { 285 if (!tigp_buffer) {
285 printf("No memory\n"); 286 printf("No memory\n");
286 return; 287 return;
287 } 288 }
288 tib_start_addr = (unsigned int *)tigp_buffer; 289 tib_start_addr = (unsigned int *)tigp_buffer;
289 blknr = inode->b.blocks.triple_indir_block; 290 blknr = inode->b.blocks.triple_indir_block;
290 status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, 291 status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
291 (char *)tigp_buffer); 292 fs->blksz, (char *)tigp_buffer);
292 for (i = 0; i < fs->blksz / sizeof(int); i++) { 293 for (i = 0; i < fs->blksz / sizeof(int); i++) {
293 if (*tigp_buffer == 0) 294 if (*tigp_buffer == 0)
294 break; 295 break;
295 debug("tigp buffer releasing %u\n", *tigp_buffer); 296 debug("tigp buffer releasing %u\n", *tigp_buffer);
296 297
297 tip_buffer = zalloc(fs->blksz); 298 tip_buffer = zalloc(fs->blksz);
298 if (!tip_buffer) 299 if (!tip_buffer)
299 goto fail; 300 goto fail;
300 tipb_start_addr = (unsigned int *)tip_buffer; 301 tipb_start_addr = (unsigned int *)tip_buffer;
301 status = ext4fs_devread((*tigp_buffer) * 302 status = ext4fs_devread((lbaint_t)(*tigp_buffer) *
302 fs->sect_perblk, 0, fs->blksz, 303 fs->sect_perblk, 0, fs->blksz,
303 (char *)tip_buffer); 304 (char *)tip_buffer);
304 for (j = 0; j < fs->blksz / sizeof(int); j++) { 305 for (j = 0; j < fs->blksz / sizeof(int); j++) {
305 if (*tip_buffer == 0) 306 if (*tip_buffer == 0)
306 break; 307 break;
307 if (fs->blksz != 1024) { 308 if (fs->blksz != 1024) {
308 bg_idx = (*tip_buffer) / blk_per_grp; 309 bg_idx = (*tip_buffer) / blk_per_grp;
309 } else { 310 } else {
310 bg_idx = (*tip_buffer) / blk_per_grp; 311 bg_idx = (*tip_buffer) / blk_per_grp;
311 312
312 remainder = (*tip_buffer) % blk_per_grp; 313 remainder = (*tip_buffer) % blk_per_grp;
313 if (!remainder) 314 if (!remainder)
314 bg_idx--; 315 bg_idx--;
315 } 316 }
316 317
317 ext4fs_reset_block_bmap(*tip_buffer, 318 ext4fs_reset_block_bmap(*tip_buffer,
318 fs->blk_bmaps[bg_idx], 319 fs->blk_bmaps[bg_idx],
319 bg_idx); 320 bg_idx);
320 321
321 tip_buffer++; 322 tip_buffer++;
322 bgd[bg_idx].free_blocks++; 323 bgd[bg_idx].free_blocks++;
323 fs->sb->free_blocks++; 324 fs->sb->free_blocks++;
324 /* journal backup */ 325 /* journal backup */
325 if (prev_bg_bmap_idx != bg_idx) { 326 if (prev_bg_bmap_idx != bg_idx) {
326 status = 327 status =
327 ext4fs_devread( 328 ext4fs_devread(
329 (lbaint_t)
328 bgd[bg_idx].block_id * 330 bgd[bg_idx].block_id *
329 fs->sect_perblk, 0, 331 fs->sect_perblk, 0,
330 fs->blksz, 332 fs->blksz,
331 journal_buffer); 333 journal_buffer);
332 if (status == 0) 334 if (status == 0)
333 goto fail; 335 goto fail;
334 336
335 if (ext4fs_log_journal(journal_buffer, 337 if (ext4fs_log_journal(journal_buffer,
336 bgd[bg_idx]. 338 bgd[bg_idx].
337 block_id)) 339 block_id))
338 goto fail; 340 goto fail;
339 prev_bg_bmap_idx = bg_idx; 341 prev_bg_bmap_idx = bg_idx;
340 } 342 }
341 } 343 }
342 free(tipb_start_addr); 344 free(tipb_start_addr);
343 tipb_start_addr = NULL; 345 tipb_start_addr = NULL;
344 346
345 /* 347 /*
346 * removing the grand parent blocks 348 * removing the grand parent blocks
347 * which is connected to inode 349 * which is connected to inode
348 */ 350 */
349 if (fs->blksz != 1024) { 351 if (fs->blksz != 1024) {
350 bg_idx = (*tigp_buffer) / blk_per_grp; 352 bg_idx = (*tigp_buffer) / blk_per_grp;
351 } else { 353 } else {
352 bg_idx = (*tigp_buffer) / blk_per_grp; 354 bg_idx = (*tigp_buffer) / blk_per_grp;
353 355
354 remainder = (*tigp_buffer) % blk_per_grp; 356 remainder = (*tigp_buffer) % blk_per_grp;
355 if (!remainder) 357 if (!remainder)
356 bg_idx--; 358 bg_idx--;
357 } 359 }
358 ext4fs_reset_block_bmap(*tigp_buffer, 360 ext4fs_reset_block_bmap(*tigp_buffer,
359 fs->blk_bmaps[bg_idx], bg_idx); 361 fs->blk_bmaps[bg_idx], bg_idx);
360 362
361 tigp_buffer++; 363 tigp_buffer++;
362 bgd[bg_idx].free_blocks++; 364 bgd[bg_idx].free_blocks++;
363 fs->sb->free_blocks++; 365 fs->sb->free_blocks++;
364 /* journal backup */ 366 /* journal backup */
365 if (prev_bg_bmap_idx != bg_idx) { 367 if (prev_bg_bmap_idx != bg_idx) {
366 memset(journal_buffer, '\0', fs->blksz); 368 memset(journal_buffer, '\0', fs->blksz);
367 status = 369 status =
368 ext4fs_devread(bgd[bg_idx].block_id * 370 ext4fs_devread((lbaint_t)
371 bgd[bg_idx].block_id *
369 fs->sect_perblk, 0, 372 fs->sect_perblk, 0,
370 fs->blksz, journal_buffer); 373 fs->blksz, journal_buffer);
371 if (status == 0) 374 if (status == 0)
372 goto fail; 375 goto fail;
373 376
374 if (ext4fs_log_journal(journal_buffer, 377 if (ext4fs_log_journal(journal_buffer,
375 bgd[bg_idx].block_id)) 378 bgd[bg_idx].block_id))
376 goto fail; 379 goto fail;
377 prev_bg_bmap_idx = bg_idx; 380 prev_bg_bmap_idx = bg_idx;
378 } 381 }
379 } 382 }
380 383
381 /* removing the grand parent triple indirect block */ 384 /* removing the grand parent triple indirect block */
382 blknr = inode->b.blocks.triple_indir_block; 385 blknr = inode->b.blocks.triple_indir_block;
383 if (fs->blksz != 1024) { 386 if (fs->blksz != 1024) {
384 bg_idx = blknr / blk_per_grp; 387 bg_idx = blknr / blk_per_grp;
385 } else { 388 } else {
386 bg_idx = blknr / blk_per_grp; 389 bg_idx = blknr / blk_per_grp;
387 remainder = blknr % blk_per_grp; 390 remainder = blknr % blk_per_grp;
388 if (!remainder) 391 if (!remainder)
389 bg_idx--; 392 bg_idx--;
390 } 393 }
391 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); 394 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
392 bgd[bg_idx].free_blocks++; 395 bgd[bg_idx].free_blocks++;
393 fs->sb->free_blocks++; 396 fs->sb->free_blocks++;
394 /* journal backup */ 397 /* journal backup */
395 if (prev_bg_bmap_idx != bg_idx) { 398 if (prev_bg_bmap_idx != bg_idx) {
396 memset(journal_buffer, '\0', fs->blksz); 399 memset(journal_buffer, '\0', fs->blksz);
397 status = ext4fs_devread(bgd[bg_idx].block_id * 400 status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
398 fs->sect_perblk, 0, fs->blksz, 401 fs->sect_perblk, 0, fs->blksz,
399 journal_buffer); 402 journal_buffer);
400 if (status == 0) 403 if (status == 0)
401 goto fail; 404 goto fail;
402 405
403 if (ext4fs_log_journal(journal_buffer, 406 if (ext4fs_log_journal(journal_buffer,
404 bgd[bg_idx].block_id)) 407 bgd[bg_idx].block_id))
405 goto fail; 408 goto fail;
406 prev_bg_bmap_idx = bg_idx; 409 prev_bg_bmap_idx = bg_idx;
407 } 410 }
408 debug("tigp buffer itself releasing %ld\n", blknr); 411 debug("tigp buffer itself releasing %ld\n", blknr);
409 } 412 }
410 fail: 413 fail:
411 free(tib_start_addr); 414 free(tib_start_addr);
412 free(tipb_start_addr); 415 free(tipb_start_addr);
413 free(journal_buffer); 416 free(journal_buffer);
414 } 417 }
415 418
416 static int ext4fs_delete_file(int inodeno) 419 static int ext4fs_delete_file(int inodeno)
417 { 420 {
418 struct ext2_inode inode; 421 struct ext2_inode inode;
419 short status; 422 short status;
420 int i; 423 int i;
421 int remainder; 424 int remainder;
422 long int blknr; 425 long int blknr;
423 int bg_idx; 426 int bg_idx;
424 int ibmap_idx; 427 int ibmap_idx;
425 char *read_buffer = NULL; 428 char *read_buffer = NULL;
426 char *start_block_address = NULL; 429 char *start_block_address = NULL;
427 unsigned int no_blocks; 430 unsigned int no_blocks;
428 431
429 static int prev_bg_bmap_idx = -1; 432 static int prev_bg_bmap_idx = -1;
430 unsigned int inodes_per_block; 433 unsigned int inodes_per_block;
431 long int blkno; 434 long int blkno;
432 unsigned int blkoff; 435 unsigned int blkoff;
433 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 436 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
434 unsigned int inode_per_grp = ext4fs_root->sblock.inodes_per_group; 437 unsigned int inode_per_grp = ext4fs_root->sblock.inodes_per_group;
435 struct ext2_inode *inode_buffer = NULL; 438 struct ext2_inode *inode_buffer = NULL;
436 struct ext2_block_group *bgd = NULL; 439 struct ext2_block_group *bgd = NULL;
437 struct ext_filesystem *fs = get_fs(); 440 struct ext_filesystem *fs = get_fs();
438 char *journal_buffer = zalloc(fs->blksz); 441 char *journal_buffer = zalloc(fs->blksz);
439 if (!journal_buffer) 442 if (!journal_buffer)
440 return -ENOMEM; 443 return -ENOMEM;
441 /* get the block group descriptor table */ 444 /* get the block group descriptor table */
442 bgd = (struct ext2_block_group *)fs->gdtable; 445 bgd = (struct ext2_block_group *)fs->gdtable;
443 status = ext4fs_read_inode(ext4fs_root, inodeno, &inode); 446 status = ext4fs_read_inode(ext4fs_root, inodeno, &inode);
444 if (status == 0) 447 if (status == 0)
445 goto fail; 448 goto fail;
446 449
447 /* read the block no allocated to a file */ 450 /* read the block no allocated to a file */
448 no_blocks = inode.size / fs->blksz; 451 no_blocks = inode.size / fs->blksz;
449 if (inode.size % fs->blksz) 452 if (inode.size % fs->blksz)
450 no_blocks++; 453 no_blocks++;
451 454
452 if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FL) { 455 if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FL) {
453 struct ext2fs_node *node_inode = 456 struct ext2fs_node *node_inode =
454 zalloc(sizeof(struct ext2fs_node)); 457 zalloc(sizeof(struct ext2fs_node));
455 if (!node_inode) 458 if (!node_inode)
456 goto fail; 459 goto fail;
457 node_inode->data = ext4fs_root; 460 node_inode->data = ext4fs_root;
458 node_inode->ino = inodeno; 461 node_inode->ino = inodeno;
459 node_inode->inode_read = 0; 462 node_inode->inode_read = 0;
460 memcpy(&(node_inode->inode), &inode, sizeof(struct ext2_inode)); 463 memcpy(&(node_inode->inode), &inode, sizeof(struct ext2_inode));
461 464
462 for (i = 0; i < no_blocks; i++) { 465 for (i = 0; i < no_blocks; i++) {
463 blknr = read_allocated_block(&(node_inode->inode), i); 466 blknr = read_allocated_block(&(node_inode->inode), i);
464 if (fs->blksz != 1024) { 467 if (fs->blksz != 1024) {
465 bg_idx = blknr / blk_per_grp; 468 bg_idx = blknr / blk_per_grp;
466 } else { 469 } else {
467 bg_idx = blknr / blk_per_grp; 470 bg_idx = blknr / blk_per_grp;
468 remainder = blknr % blk_per_grp; 471 remainder = blknr % blk_per_grp;
469 if (!remainder) 472 if (!remainder)
470 bg_idx--; 473 bg_idx--;
471 } 474 }
472 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], 475 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx],
473 bg_idx); 476 bg_idx);
474 debug("EXT4_EXTENTS Block releasing %ld: %d\n", 477 debug("EXT4_EXTENTS Block releasing %ld: %d\n",
475 blknr, bg_idx); 478 blknr, bg_idx);
476 479
477 bgd[bg_idx].free_blocks++; 480 bgd[bg_idx].free_blocks++;
478 fs->sb->free_blocks++; 481 fs->sb->free_blocks++;
479 482
480 /* journal backup */ 483 /* journal backup */
481 if (prev_bg_bmap_idx != bg_idx) { 484 if (prev_bg_bmap_idx != bg_idx) {
482 status = 485 status =
483 ext4fs_devread(bgd[bg_idx].block_id * 486 ext4fs_devread((lbaint_t)
487 bgd[bg_idx].block_id *
484 fs->sect_perblk, 0, 488 fs->sect_perblk, 0,
485 fs->blksz, journal_buffer); 489 fs->blksz, journal_buffer);
486 if (status == 0) 490 if (status == 0)
487 goto fail; 491 goto fail;
488 if (ext4fs_log_journal(journal_buffer, 492 if (ext4fs_log_journal(journal_buffer,
489 bgd[bg_idx].block_id)) 493 bgd[bg_idx].block_id))
490 goto fail; 494 goto fail;
491 prev_bg_bmap_idx = bg_idx; 495 prev_bg_bmap_idx = bg_idx;
492 } 496 }
493 } 497 }
494 if (node_inode) { 498 if (node_inode) {
495 free(node_inode); 499 free(node_inode);
496 node_inode = NULL; 500 node_inode = NULL;
497 } 501 }
498 } else { 502 } else {
499 503
500 delete_single_indirect_block(&inode); 504 delete_single_indirect_block(&inode);
501 delete_double_indirect_block(&inode); 505 delete_double_indirect_block(&inode);
502 delete_triple_indirect_block(&inode); 506 delete_triple_indirect_block(&inode);
503 507
504 /* read the block no allocated to a file */ 508 /* read the block no allocated to a file */
505 no_blocks = inode.size / fs->blksz; 509 no_blocks = inode.size / fs->blksz;
506 if (inode.size % fs->blksz) 510 if (inode.size % fs->blksz)
507 no_blocks++; 511 no_blocks++;
508 for (i = 0; i < no_blocks; i++) { 512 for (i = 0; i < no_blocks; i++) {
509 blknr = read_allocated_block(&inode, i); 513 blknr = read_allocated_block(&inode, i);
510 if (fs->blksz != 1024) { 514 if (fs->blksz != 1024) {
511 bg_idx = blknr / blk_per_grp; 515 bg_idx = blknr / blk_per_grp;
512 } else { 516 } else {
513 bg_idx = blknr / blk_per_grp; 517 bg_idx = blknr / blk_per_grp;
514 remainder = blknr % blk_per_grp; 518 remainder = blknr % blk_per_grp;
515 if (!remainder) 519 if (!remainder)
516 bg_idx--; 520 bg_idx--;
517 } 521 }
518 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], 522 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx],
519 bg_idx); 523 bg_idx);
520 debug("ActualB releasing %ld: %d\n", blknr, bg_idx); 524 debug("ActualB releasing %ld: %d\n", blknr, bg_idx);
521 525
522 bgd[bg_idx].free_blocks++; 526 bgd[bg_idx].free_blocks++;
523 fs->sb->free_blocks++; 527 fs->sb->free_blocks++;
524 /* journal backup */ 528 /* journal backup */
525 if (prev_bg_bmap_idx != bg_idx) { 529 if (prev_bg_bmap_idx != bg_idx) {
526 memset(journal_buffer, '\0', fs->blksz); 530 memset(journal_buffer, '\0', fs->blksz);
527 status = ext4fs_devread(bgd[bg_idx].block_id 531 status = ext4fs_devread((lbaint_t)
532 bgd[bg_idx].block_id
528 * fs->sect_perblk, 533 * fs->sect_perblk,
529 0, fs->blksz, 534 0, fs->blksz,
530 journal_buffer); 535 journal_buffer);
531 if (status == 0) 536 if (status == 0)
532 goto fail; 537 goto fail;
533 if (ext4fs_log_journal(journal_buffer, 538 if (ext4fs_log_journal(journal_buffer,
534 bgd[bg_idx].block_id)) 539 bgd[bg_idx].block_id))
535 goto fail; 540 goto fail;
536 prev_bg_bmap_idx = bg_idx; 541 prev_bg_bmap_idx = bg_idx;
537 } 542 }
538 } 543 }
539 } 544 }
540 545
541 /* from the inode no to blockno */ 546 /* from the inode no to blockno */
542 inodes_per_block = fs->blksz / fs->inodesz; 547 inodes_per_block = fs->blksz / fs->inodesz;
543 ibmap_idx = inodeno / inode_per_grp; 548 ibmap_idx = inodeno / inode_per_grp;
544 549
545 /* get the block no */ 550 /* get the block no */
546 inodeno--; 551 inodeno--;
547 blkno = __le32_to_cpu(bgd[ibmap_idx].inode_table_id) + 552 blkno = __le32_to_cpu(bgd[ibmap_idx].inode_table_id) +
548 (inodeno % __le32_to_cpu(inode_per_grp)) / inodes_per_block; 553 (inodeno % __le32_to_cpu(inode_per_grp)) / inodes_per_block;
549 554
550 /* get the offset of the inode */ 555 /* get the offset of the inode */
551 blkoff = ((inodeno) % inodes_per_block) * fs->inodesz; 556 blkoff = ((inodeno) % inodes_per_block) * fs->inodesz;
552 557
553 /* read the block no containing the inode */ 558 /* read the block no containing the inode */
554 read_buffer = zalloc(fs->blksz); 559 read_buffer = zalloc(fs->blksz);
555 if (!read_buffer) 560 if (!read_buffer)
556 goto fail; 561 goto fail;
557 start_block_address = read_buffer; 562 start_block_address = read_buffer;
558 status = ext4fs_devread(blkno * fs->sect_perblk, 563 status = ext4fs_devread((lbaint_t)blkno * fs->sect_perblk,
559 0, fs->blksz, read_buffer); 564 0, fs->blksz, read_buffer);
560 if (status == 0) 565 if (status == 0)
561 goto fail; 566 goto fail;
562 567
563 if (ext4fs_log_journal(read_buffer, blkno)) 568 if (ext4fs_log_journal(read_buffer, blkno))
564 goto fail; 569 goto fail;
565 570
566 read_buffer = read_buffer + blkoff; 571 read_buffer = read_buffer + blkoff;
567 inode_buffer = (struct ext2_inode *)read_buffer; 572 inode_buffer = (struct ext2_inode *)read_buffer;
568 memset(inode_buffer, '\0', sizeof(struct ext2_inode)); 573 memset(inode_buffer, '\0', sizeof(struct ext2_inode));
569 574
570 /* write the inode to original position in inode table */ 575 /* write the inode to original position in inode table */
571 if (ext4fs_put_metadata(start_block_address, blkno)) 576 if (ext4fs_put_metadata(start_block_address, blkno))
572 goto fail; 577 goto fail;
573 578
574 /* update the respective inode bitmaps */ 579 /* update the respective inode bitmaps */
575 inodeno++; 580 inodeno++;
576 ext4fs_reset_inode_bmap(inodeno, fs->inode_bmaps[ibmap_idx], ibmap_idx); 581 ext4fs_reset_inode_bmap(inodeno, fs->inode_bmaps[ibmap_idx], ibmap_idx);
577 bgd[ibmap_idx].free_inodes++; 582 bgd[ibmap_idx].free_inodes++;
578 fs->sb->free_inodes++; 583 fs->sb->free_inodes++;
579 /* journal backup */ 584 /* journal backup */
580 memset(journal_buffer, '\0', fs->blksz); 585 memset(journal_buffer, '\0', fs->blksz);
581 status = ext4fs_devread(bgd[ibmap_idx].inode_id * 586 status = ext4fs_devread((lbaint_t)bgd[ibmap_idx].inode_id *
582 fs->sect_perblk, 0, fs->blksz, journal_buffer); 587 fs->sect_perblk, 0, fs->blksz, journal_buffer);
583 if (status == 0) 588 if (status == 0)
584 goto fail; 589 goto fail;
585 if (ext4fs_log_journal(journal_buffer, bgd[ibmap_idx].inode_id)) 590 if (ext4fs_log_journal(journal_buffer, bgd[ibmap_idx].inode_id))
586 goto fail; 591 goto fail;
587 592
588 ext4fs_update(); 593 ext4fs_update();
589 ext4fs_deinit(); 594 ext4fs_deinit();
590 595
591 if (ext4fs_init() != 0) { 596 if (ext4fs_init() != 0) {
592 printf("error in File System init\n"); 597 printf("error in File System init\n");
593 goto fail; 598 goto fail;
594 } 599 }
595 600
596 free(start_block_address); 601 free(start_block_address);
597 free(journal_buffer); 602 free(journal_buffer);
598 603
599 return 0; 604 return 0;
600 fail: 605 fail:
601 free(start_block_address); 606 free(start_block_address);
602 free(journal_buffer); 607 free(journal_buffer);
603 608
604 return -1; 609 return -1;
605 } 610 }
606 611
607 int ext4fs_init(void) 612 int ext4fs_init(void)
608 { 613 {
609 short status; 614 short status;
610 int i; 615 int i;
611 unsigned int real_free_blocks = 0; 616 unsigned int real_free_blocks = 0;
612 struct ext_filesystem *fs = get_fs(); 617 struct ext_filesystem *fs = get_fs();
613 618
614 /* populate fs */ 619 /* populate fs */
615 fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root); 620 fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root);
616 fs->inodesz = INODE_SIZE_FILESYSTEM(ext4fs_root); 621 fs->inodesz = INODE_SIZE_FILESYSTEM(ext4fs_root);
617 fs->sect_perblk = fs->blksz >> fs->dev_desc->log2blksz; 622 fs->sect_perblk = fs->blksz >> fs->dev_desc->log2blksz;
618 623
619 /* get the superblock */ 624 /* get the superblock */
620 fs->sb = zalloc(SUPERBLOCK_SIZE); 625 fs->sb = zalloc(SUPERBLOCK_SIZE);
621 if (!fs->sb) 626 if (!fs->sb)
622 return -ENOMEM; 627 return -ENOMEM;
623 if (!ext4_read_superblock((char *)fs->sb)) 628 if (!ext4_read_superblock((char *)fs->sb))
624 goto fail; 629 goto fail;
625 630
626 /* init journal */ 631 /* init journal */
627 if (ext4fs_init_journal()) 632 if (ext4fs_init_journal())
628 goto fail; 633 goto fail;
629 634
630 /* get total no of blockgroups */ 635 /* get total no of blockgroups */
631 fs->no_blkgrp = (uint32_t)ext4fs_div_roundup( 636 fs->no_blkgrp = (uint32_t)ext4fs_div_roundup(
632 (ext4fs_root->sblock.total_blocks - 637 (ext4fs_root->sblock.total_blocks -
633 ext4fs_root->sblock.first_data_block), 638 ext4fs_root->sblock.first_data_block),
634 ext4fs_root->sblock.blocks_per_group); 639 ext4fs_root->sblock.blocks_per_group);
635 640
636 /* get the block group descriptor table */ 641 /* get the block group descriptor table */
637 fs->gdtable_blkno = ((EXT2_MIN_BLOCK_SIZE == fs->blksz) + 1); 642 fs->gdtable_blkno = ((EXT2_MIN_BLOCK_SIZE == fs->blksz) + 1);
638 if (ext4fs_get_bgdtable() == -1) { 643 if (ext4fs_get_bgdtable() == -1) {
639 printf("Error in getting the block group descriptor table\n"); 644 printf("Error in getting the block group descriptor table\n");
640 goto fail; 645 goto fail;
641 } 646 }
642 fs->bgd = (struct ext2_block_group *)fs->gdtable; 647 fs->bgd = (struct ext2_block_group *)fs->gdtable;
643 648
644 /* load all the available bitmap block of the partition */ 649 /* load all the available bitmap block of the partition */
645 fs->blk_bmaps = zalloc(fs->no_blkgrp * sizeof(char *)); 650 fs->blk_bmaps = zalloc(fs->no_blkgrp * sizeof(char *));
646 if (!fs->blk_bmaps) 651 if (!fs->blk_bmaps)
647 goto fail; 652 goto fail;
648 for (i = 0; i < fs->no_blkgrp; i++) { 653 for (i = 0; i < fs->no_blkgrp; i++) {
649 fs->blk_bmaps[i] = zalloc(fs->blksz); 654 fs->blk_bmaps[i] = zalloc(fs->blksz);
650 if (!fs->blk_bmaps[i]) 655 if (!fs->blk_bmaps[i])
651 goto fail; 656 goto fail;
652 } 657 }
653 658
654 for (i = 0; i < fs->no_blkgrp; i++) { 659 for (i = 0; i < fs->no_blkgrp; i++) {
655 status = 660 status =
656 ext4fs_devread(fs->bgd[i].block_id * fs->sect_perblk, 0, 661 ext4fs_devread((lbaint_t)fs->bgd[i].block_id *
662 fs->sect_perblk, 0,
657 fs->blksz, (char *)fs->blk_bmaps[i]); 663 fs->blksz, (char *)fs->blk_bmaps[i]);
658 if (status == 0) 664 if (status == 0)
659 goto fail; 665 goto fail;
660 } 666 }
661 667
662 /* load all the available inode bitmap of the partition */ 668 /* load all the available inode bitmap of the partition */
663 fs->inode_bmaps = zalloc(fs->no_blkgrp * sizeof(unsigned char *)); 669 fs->inode_bmaps = zalloc(fs->no_blkgrp * sizeof(unsigned char *));
664 if (!fs->inode_bmaps) 670 if (!fs->inode_bmaps)
665 goto fail; 671 goto fail;
666 for (i = 0; i < fs->no_blkgrp; i++) { 672 for (i = 0; i < fs->no_blkgrp; i++) {
667 fs->inode_bmaps[i] = zalloc(fs->blksz); 673 fs->inode_bmaps[i] = zalloc(fs->blksz);
668 if (!fs->inode_bmaps[i]) 674 if (!fs->inode_bmaps[i])
669 goto fail; 675 goto fail;
670 } 676 }
671 677
672 for (i = 0; i < fs->no_blkgrp; i++) { 678 for (i = 0; i < fs->no_blkgrp; i++) {
673 status = ext4fs_devread(fs->bgd[i].inode_id * fs->sect_perblk, 679 status = ext4fs_devread((lbaint_t)fs->bgd[i].inode_id *
680 fs->sect_perblk,
674 0, fs->blksz, 681 0, fs->blksz,
675 (char *)fs->inode_bmaps[i]); 682 (char *)fs->inode_bmaps[i]);
676 if (status == 0) 683 if (status == 0)
677 goto fail; 684 goto fail;
678 } 685 }
679 686
680 /* 687 /*
681 * check filesystem consistency with free blocks of file system 688 * check filesystem consistency with free blocks of file system
682 * some time we observed that superblock freeblocks does not match 689 * some time we observed that superblock freeblocks does not match
683 * with the blockgroups freeblocks when improper 690 * with the blockgroups freeblocks when improper
684 * reboot of a linux kernel 691 * reboot of a linux kernel
685 */ 692 */
686 for (i = 0; i < fs->no_blkgrp; i++) 693 for (i = 0; i < fs->no_blkgrp; i++)
687 real_free_blocks = real_free_blocks + fs->bgd[i].free_blocks; 694 real_free_blocks = real_free_blocks + fs->bgd[i].free_blocks;
688 if (real_free_blocks != fs->sb->free_blocks) 695 if (real_free_blocks != fs->sb->free_blocks)
689 fs->sb->free_blocks = real_free_blocks; 696 fs->sb->free_blocks = real_free_blocks;
690 697
691 return 0; 698 return 0;
692 fail: 699 fail:
693 ext4fs_deinit(); 700 ext4fs_deinit();
694 701
695 return -1; 702 return -1;
696 } 703 }
697 704
698 void ext4fs_deinit(void) 705 void ext4fs_deinit(void)
699 { 706 {
700 int i; 707 int i;
701 struct ext2_inode inode_journal; 708 struct ext2_inode inode_journal;
702 struct journal_superblock_t *jsb; 709 struct journal_superblock_t *jsb;
703 long int blknr; 710 long int blknr;
704 struct ext_filesystem *fs = get_fs(); 711 struct ext_filesystem *fs = get_fs();
705 712
706 /* free journal */ 713 /* free journal */
707 char *temp_buff = zalloc(fs->blksz); 714 char *temp_buff = zalloc(fs->blksz);
708 if (temp_buff) { 715 if (temp_buff) {
709 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, 716 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
710 &inode_journal); 717 &inode_journal);
711 blknr = read_allocated_block(&inode_journal, 718 blknr = read_allocated_block(&inode_journal,
712 EXT2_JOURNAL_SUPERBLOCK); 719 EXT2_JOURNAL_SUPERBLOCK);
713 ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, 720 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
714 temp_buff); 721 temp_buff);
715 jsb = (struct journal_superblock_t *)temp_buff; 722 jsb = (struct journal_superblock_t *)temp_buff;
716 jsb->s_start = cpu_to_be32(0); 723 jsb->s_start = cpu_to_be32(0);
717 put_ext4((uint64_t) (blknr * fs->blksz), 724 put_ext4((uint64_t) (blknr * fs->blksz),
718 (struct journal_superblock_t *)temp_buff, fs->blksz); 725 (struct journal_superblock_t *)temp_buff, fs->blksz);
719 free(temp_buff); 726 free(temp_buff);
720 } 727 }
721 ext4fs_free_journal(); 728 ext4fs_free_journal();
722 729
723 /* get the superblock */ 730 /* get the superblock */
724 ext4_read_superblock((char *)fs->sb); 731 ext4_read_superblock((char *)fs->sb);
725 fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; 732 fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
726 put_ext4((uint64_t)(SUPERBLOCK_SIZE), 733 put_ext4((uint64_t)(SUPERBLOCK_SIZE),
727 (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE); 734 (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE);
728 free(fs->sb); 735 free(fs->sb);
729 fs->sb = NULL; 736 fs->sb = NULL;
730 737
731 if (fs->blk_bmaps) { 738 if (fs->blk_bmaps) {
732 for (i = 0; i < fs->no_blkgrp; i++) { 739 for (i = 0; i < fs->no_blkgrp; i++) {
733 free(fs->blk_bmaps[i]); 740 free(fs->blk_bmaps[i]);
734 fs->blk_bmaps[i] = NULL; 741 fs->blk_bmaps[i] = NULL;
735 } 742 }
736 free(fs->blk_bmaps); 743 free(fs->blk_bmaps);
737 fs->blk_bmaps = NULL; 744 fs->blk_bmaps = NULL;
738 } 745 }
739 746
740 if (fs->inode_bmaps) { 747 if (fs->inode_bmaps) {
741 for (i = 0; i < fs->no_blkgrp; i++) { 748 for (i = 0; i < fs->no_blkgrp; i++) {
742 free(fs->inode_bmaps[i]); 749 free(fs->inode_bmaps[i]);
743 fs->inode_bmaps[i] = NULL; 750 fs->inode_bmaps[i] = NULL;
744 } 751 }
745 free(fs->inode_bmaps); 752 free(fs->inode_bmaps);
746 fs->inode_bmaps = NULL; 753 fs->inode_bmaps = NULL;
747 } 754 }
748 755
749 756
750 free(fs->gdtable); 757 free(fs->gdtable);
751 fs->gdtable = NULL; 758 fs->gdtable = NULL;
752 fs->bgd = NULL; 759 fs->bgd = NULL;
753 /* 760 /*
754 * reinitiliazed the global inode and 761 * reinitiliazed the global inode and
755 * block bitmap first execution check variables 762 * block bitmap first execution check variables
756 */ 763 */
757 fs->first_pass_ibmap = 0; 764 fs->first_pass_ibmap = 0;
758 fs->first_pass_bbmap = 0; 765 fs->first_pass_bbmap = 0;
759 fs->curr_inode_no = 0; 766 fs->curr_inode_no = 0;
760 fs->curr_blkno = 0; 767 fs->curr_blkno = 0;
761 } 768 }
762 769
763 static int ext4fs_write_file(struct ext2_inode *file_inode, 770 static int ext4fs_write_file(struct ext2_inode *file_inode,
764 int pos, unsigned int len, char *buf) 771 int pos, unsigned int len, char *buf)
765 { 772 {
766 int i; 773 int i;
767 int blockcnt; 774 int blockcnt;
768 unsigned int filesize = __le32_to_cpu(file_inode->size); 775 unsigned int filesize = __le32_to_cpu(file_inode->size);
769 struct ext_filesystem *fs = get_fs(); 776 struct ext_filesystem *fs = get_fs();
770 int log2blksz = fs->dev_desc->log2blksz; 777 int log2blksz = fs->dev_desc->log2blksz;
771 int log2_fs_blocksize = LOG2_BLOCK_SIZE(ext4fs_root) - log2blksz; 778 int log2_fs_blocksize = LOG2_BLOCK_SIZE(ext4fs_root) - log2blksz;
772 int previous_block_number = -1; 779 int previous_block_number = -1;
773 int delayed_start = 0; 780 int delayed_start = 0;
774 int delayed_extent = 0; 781 int delayed_extent = 0;
775 int delayed_next = 0; 782 int delayed_next = 0;
776 char *delayed_buf = NULL; 783 char *delayed_buf = NULL;
777 784
778 /* Adjust len so it we can't read past the end of the file. */ 785 /* Adjust len so it we can't read past the end of the file. */
779 if (len > filesize) 786 if (len > filesize)
780 len = filesize; 787 len = filesize;
781 788
782 blockcnt = ((len + pos) + fs->blksz - 1) / fs->blksz; 789 blockcnt = ((len + pos) + fs->blksz - 1) / fs->blksz;
783 790
784 for (i = pos / fs->blksz; i < blockcnt; i++) { 791 for (i = pos / fs->blksz; i < blockcnt; i++) {
785 long int blknr; 792 long int blknr;
786 int blockend = fs->blksz; 793 int blockend = fs->blksz;
787 int skipfirst = 0; 794 int skipfirst = 0;
788 blknr = read_allocated_block(file_inode, i); 795 blknr = read_allocated_block(file_inode, i);
789 if (blknr < 0) 796 if (blknr < 0)
790 return -1; 797 return -1;
791 798
792 blknr = blknr << log2_fs_blocksize; 799 blknr = blknr << log2_fs_blocksize;
793 800
794 if (blknr) { 801 if (blknr) {
795 if (previous_block_number != -1) { 802 if (previous_block_number != -1) {
796 if (delayed_next == blknr) { 803 if (delayed_next == blknr) {
797 delayed_extent += blockend; 804 delayed_extent += blockend;
798 delayed_next += blockend >> log2blksz; 805 delayed_next += blockend >> log2blksz;
799 } else { /* spill */ 806 } else { /* spill */
800 put_ext4((uint64_t) 807 put_ext4((uint64_t)
801 (delayed_start << log2blksz), 808 (delayed_start << log2blksz),
802 delayed_buf, 809 delayed_buf,
803 (uint32_t) delayed_extent); 810 (uint32_t) delayed_extent);
804 previous_block_number = blknr; 811 previous_block_number = blknr;
805 delayed_start = blknr; 812 delayed_start = blknr;
806 delayed_extent = blockend; 813 delayed_extent = blockend;
807 delayed_buf = buf; 814 delayed_buf = buf;
808 delayed_next = blknr + 815 delayed_next = blknr +
809 (blockend >> log2blksz); 816 (blockend >> log2blksz);
810 } 817 }
811 } else { 818 } else {
812 previous_block_number = blknr; 819 previous_block_number = blknr;
813 delayed_start = blknr; 820 delayed_start = blknr;
814 delayed_extent = blockend; 821 delayed_extent = blockend;
815 delayed_buf = buf; 822 delayed_buf = buf;
816 delayed_next = blknr + 823 delayed_next = blknr +
817 (blockend >> log2blksz); 824 (blockend >> log2blksz);
818 } 825 }
819 } else { 826 } else {
820 if (previous_block_number != -1) { 827 if (previous_block_number != -1) {
821 /* spill */ 828 /* spill */
822 put_ext4((uint64_t) (delayed_start << 829 put_ext4((uint64_t) (delayed_start <<
823 log2blksz), 830 log2blksz),
824 delayed_buf, 831 delayed_buf,
825 (uint32_t) delayed_extent); 832 (uint32_t) delayed_extent);
826 previous_block_number = -1; 833 previous_block_number = -1;
827 } 834 }
828 memset(buf, 0, fs->blksz - skipfirst); 835 memset(buf, 0, fs->blksz - skipfirst);
829 } 836 }
830 buf += fs->blksz - skipfirst; 837 buf += fs->blksz - skipfirst;
831 } 838 }
832 if (previous_block_number != -1) { 839 if (previous_block_number != -1) {
833 /* spill */ 840 /* spill */
834 put_ext4((uint64_t) (delayed_start << log2blksz), 841 put_ext4((uint64_t) (delayed_start << log2blksz),
835 delayed_buf, (uint32_t) delayed_extent); 842 delayed_buf, (uint32_t) delayed_extent);
836 previous_block_number = -1; 843 previous_block_number = -1;
837 } 844 }
838 845
839 return len; 846 return len;
840 } 847 }
841 848
842 int ext4fs_write(const char *fname, unsigned char *buffer, 849 int ext4fs_write(const char *fname, unsigned char *buffer,
843 unsigned long sizebytes) 850 unsigned long sizebytes)
844 { 851 {
845 int ret = 0; 852 int ret = 0;
846 struct ext2_inode *file_inode = NULL; 853 struct ext2_inode *file_inode = NULL;
847 unsigned char *inode_buffer = NULL; 854 unsigned char *inode_buffer = NULL;
848 int parent_inodeno; 855 int parent_inodeno;
849 int inodeno; 856 int inodeno;
850 time_t timestamp = 0; 857 time_t timestamp = 0;
851 858
852 uint64_t bytes_reqd_for_file; 859 uint64_t bytes_reqd_for_file;
853 unsigned int blks_reqd_for_file; 860 unsigned int blks_reqd_for_file;
854 unsigned int blocks_remaining; 861 unsigned int blocks_remaining;
855 int existing_file_inodeno; 862 int existing_file_inodeno;
856 char *temp_ptr = NULL; 863 char *temp_ptr = NULL;
857 long int itable_blkno; 864 long int itable_blkno;
858 long int parent_itable_blkno; 865 long int parent_itable_blkno;
859 long int blkoff; 866 long int blkoff;
860 struct ext2_sblock *sblock = &(ext4fs_root->sblock); 867 struct ext2_sblock *sblock = &(ext4fs_root->sblock);
861 unsigned int inodes_per_block; 868 unsigned int inodes_per_block;
862 unsigned int ibmap_idx; 869 unsigned int ibmap_idx;
863 struct ext_filesystem *fs = get_fs(); 870 struct ext_filesystem *fs = get_fs();
864 ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256); 871 ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256);
865 memset(filename, 0x00, sizeof(filename)); 872 memset(filename, 0x00, sizeof(filename));
866 873
867 g_parent_inode = zalloc(sizeof(struct ext2_inode)); 874 g_parent_inode = zalloc(sizeof(struct ext2_inode));
868 if (!g_parent_inode) 875 if (!g_parent_inode)
869 goto fail; 876 goto fail;
870 877
871 if (ext4fs_init() != 0) { 878 if (ext4fs_init() != 0) {
872 printf("error in File System init\n"); 879 printf("error in File System init\n");
873 return -1; 880 return -1;
874 } 881 }
875 inodes_per_block = fs->blksz / fs->inodesz; 882 inodes_per_block = fs->blksz / fs->inodesz;
876 parent_inodeno = ext4fs_get_parent_inode_num(fname, filename, F_FILE); 883 parent_inodeno = ext4fs_get_parent_inode_num(fname, filename, F_FILE);
877 if (parent_inodeno == -1) 884 if (parent_inodeno == -1)
878 goto fail; 885 goto fail;
879 if (ext4fs_iget(parent_inodeno, g_parent_inode)) 886 if (ext4fs_iget(parent_inodeno, g_parent_inode))
880 goto fail; 887 goto fail;
881 /* check if the filename is already present in root */ 888 /* check if the filename is already present in root */
882 existing_file_inodeno = ext4fs_filename_check(filename); 889 existing_file_inodeno = ext4fs_filename_check(filename);
883 if (existing_file_inodeno != -1) { 890 if (existing_file_inodeno != -1) {
884 ret = ext4fs_delete_file(existing_file_inodeno); 891 ret = ext4fs_delete_file(existing_file_inodeno);
885 fs->first_pass_bbmap = 0; 892 fs->first_pass_bbmap = 0;
886 fs->curr_blkno = 0; 893 fs->curr_blkno = 0;
887 894
888 fs->first_pass_ibmap = 0; 895 fs->first_pass_ibmap = 0;
889 fs->curr_inode_no = 0; 896 fs->curr_inode_no = 0;
890 if (ret) 897 if (ret)
891 goto fail; 898 goto fail;
892 } 899 }
893 /* calucalate how many blocks required */ 900 /* calucalate how many blocks required */
894 bytes_reqd_for_file = sizebytes; 901 bytes_reqd_for_file = sizebytes;
895 blks_reqd_for_file = lldiv(bytes_reqd_for_file, fs->blksz); 902 blks_reqd_for_file = lldiv(bytes_reqd_for_file, fs->blksz);
896 if (do_div(bytes_reqd_for_file, fs->blksz) != 0) { 903 if (do_div(bytes_reqd_for_file, fs->blksz) != 0) {
897 blks_reqd_for_file++; 904 blks_reqd_for_file++;
898 debug("total bytes for a file %u\n", blks_reqd_for_file); 905 debug("total bytes for a file %u\n", blks_reqd_for_file);
899 } 906 }
900 blocks_remaining = blks_reqd_for_file; 907 blocks_remaining = blks_reqd_for_file;
901 /* test for available space in partition */ 908 /* test for available space in partition */
902 if (fs->sb->free_blocks < blks_reqd_for_file) { 909 if (fs->sb->free_blocks < blks_reqd_for_file) {
903 printf("Not enough space on partition !!!\n"); 910 printf("Not enough space on partition !!!\n");
904 goto fail; 911 goto fail;
905 } 912 }
906 913
907 ext4fs_update_parent_dentry(filename, &inodeno, FILETYPE_REG); 914 ext4fs_update_parent_dentry(filename, &inodeno, FILETYPE_REG);
908 /* prepare file inode */ 915 /* prepare file inode */
909 inode_buffer = zalloc(fs->inodesz); 916 inode_buffer = zalloc(fs->inodesz);
910 if (!inode_buffer) 917 if (!inode_buffer)
911 goto fail; 918 goto fail;
912 file_inode = (struct ext2_inode *)inode_buffer; 919 file_inode = (struct ext2_inode *)inode_buffer;
913 file_inode->mode = S_IFREG | S_IRWXU | 920 file_inode->mode = S_IFREG | S_IRWXU |
914 S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH; 921 S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH;
915 /* ToDo: Update correct time */ 922 /* ToDo: Update correct time */
916 file_inode->mtime = timestamp; 923 file_inode->mtime = timestamp;
917 file_inode->atime = timestamp; 924 file_inode->atime = timestamp;
918 file_inode->ctime = timestamp; 925 file_inode->ctime = timestamp;
919 file_inode->nlinks = 1; 926 file_inode->nlinks = 1;
920 file_inode->size = sizebytes; 927 file_inode->size = sizebytes;
921 928
922 /* Allocate data blocks */ 929 /* Allocate data blocks */
923 ext4fs_allocate_blocks(file_inode, blocks_remaining, 930 ext4fs_allocate_blocks(file_inode, blocks_remaining,
924 &blks_reqd_for_file); 931 &blks_reqd_for_file);
925 file_inode->blockcnt = (blks_reqd_for_file * fs->blksz) >> 932 file_inode->blockcnt = (blks_reqd_for_file * fs->blksz) >>
926 fs->dev_desc->log2blksz; 933 fs->dev_desc->log2blksz;
927 934
928 temp_ptr = zalloc(fs->blksz); 935 temp_ptr = zalloc(fs->blksz);
929 if (!temp_ptr) 936 if (!temp_ptr)
930 goto fail; 937 goto fail;
931 ibmap_idx = inodeno / ext4fs_root->sblock.inodes_per_group; 938 ibmap_idx = inodeno / ext4fs_root->sblock.inodes_per_group;
932 inodeno--; 939 inodeno--;
933 itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) + 940 itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) +
934 (inodeno % __le32_to_cpu(sblock->inodes_per_group)) / 941 (inodeno % __le32_to_cpu(sblock->inodes_per_group)) /
935 inodes_per_block; 942 inodes_per_block;
936 blkoff = (inodeno % inodes_per_block) * fs->inodesz; 943 blkoff = (inodeno % inodes_per_block) * fs->inodesz;
937 ext4fs_devread(itable_blkno * fs->sect_perblk, 0, fs->blksz, temp_ptr); 944 ext4fs_devread((lbaint_t)itable_blkno * fs->sect_perblk, 0, fs->blksz,
945 temp_ptr);
938 if (ext4fs_log_journal(temp_ptr, itable_blkno)) 946 if (ext4fs_log_journal(temp_ptr, itable_blkno))
939 goto fail; 947 goto fail;
940 948
941 memcpy(temp_ptr + blkoff, inode_buffer, fs->inodesz); 949 memcpy(temp_ptr + blkoff, inode_buffer, fs->inodesz);
942 if (ext4fs_put_metadata(temp_ptr, itable_blkno)) 950 if (ext4fs_put_metadata(temp_ptr, itable_blkno))
943 goto fail; 951 goto fail;
944 /* copy the file content into data blocks */ 952 /* copy the file content into data blocks */
945 if (ext4fs_write_file(file_inode, 0, sizebytes, (char *)buffer) == -1) { 953 if (ext4fs_write_file(file_inode, 0, sizebytes, (char *)buffer) == -1) {
946 printf("Error in copying content\n"); 954 printf("Error in copying content\n");
947 goto fail; 955 goto fail;
948 } 956 }
949 ibmap_idx = parent_inodeno / ext4fs_root->sblock.inodes_per_group; 957 ibmap_idx = parent_inodeno / ext4fs_root->sblock.inodes_per_group;
950 parent_inodeno--; 958 parent_inodeno--;
951 parent_itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) + 959 parent_itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) +
952 (parent_inodeno % 960 (parent_inodeno %
953 __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; 961 __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
954 blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz; 962 blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz;
955 if (parent_itable_blkno != itable_blkno) { 963 if (parent_itable_blkno != itable_blkno) {
956 memset(temp_ptr, '\0', fs->blksz); 964 memset(temp_ptr, '\0', fs->blksz);
957 ext4fs_devread(parent_itable_blkno * fs->sect_perblk, 965 ext4fs_devread((lbaint_t)parent_itable_blkno * fs->sect_perblk,
958 0, fs->blksz, temp_ptr); 966 0, fs->blksz, temp_ptr);
959 if (ext4fs_log_journal(temp_ptr, parent_itable_blkno)) 967 if (ext4fs_log_journal(temp_ptr, parent_itable_blkno))
960 goto fail; 968 goto fail;
961 969
962 memcpy(temp_ptr + blkoff, g_parent_inode, 970 memcpy(temp_ptr + blkoff, g_parent_inode,
963 sizeof(struct ext2_inode)); 971 sizeof(struct ext2_inode));
964 if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno)) 972 if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno))
965 goto fail; 973 goto fail;
966 free(temp_ptr); 974 free(temp_ptr);
967 } else { 975 } else {
968 /* 976 /*
969 * If parent and child fall in same inode table block 977 * If parent and child fall in same inode table block
970 * both should be kept in 1 buffer 978 * both should be kept in 1 buffer
971 */ 979 */
972 memcpy(temp_ptr + blkoff, g_parent_inode, 980 memcpy(temp_ptr + blkoff, g_parent_inode,
973 sizeof(struct ext2_inode)); 981 sizeof(struct ext2_inode));
974 gd_index--; 982 gd_index--;
975 if (ext4fs_put_metadata(temp_ptr, itable_blkno)) 983 if (ext4fs_put_metadata(temp_ptr, itable_blkno))
976 goto fail; 984 goto fail;
977 free(temp_ptr); 985 free(temp_ptr);
978 } 986 }
979 ext4fs_update(); 987 ext4fs_update();
980 ext4fs_deinit(); 988 ext4fs_deinit();
981 989
982 fs->first_pass_bbmap = 0; 990 fs->first_pass_bbmap = 0;
983 fs->curr_blkno = 0; 991 fs->curr_blkno = 0;
984 fs->first_pass_ibmap = 0; 992 fs->first_pass_ibmap = 0;
985 fs->curr_inode_no = 0; 993 fs->curr_inode_no = 0;
986 free(inode_buffer); 994 free(inode_buffer);
987 free(g_parent_inode); 995 free(g_parent_inode);
988 g_parent_inode = NULL; 996 g_parent_inode = NULL;
989 997
990 return 0; 998 return 0;
991 fail: 999 fail:
992 ext4fs_deinit(); 1000 ext4fs_deinit();
993 free(inode_buffer); 1001 free(inode_buffer);
994 free(g_parent_inode); 1002 free(g_parent_inode);
995 g_parent_inode = NULL; 1003 g_parent_inode = NULL;
996 1004
997 return -1; 1005 return -1;
998 } 1006 }
999 1007
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * ext4ls and ext4load : Based on ext2 ls and load support in Uboot. 7 * ext4ls and ext4load : Based on ext2 ls and load support in Uboot.
8 * Ext4 read optimization taken from Open-Moko 8 * Ext4 read optimization taken from Open-Moko
9 * Qi bootloader 9 * Qi bootloader
10 * 10 *
11 * (C) Copyright 2004 11 * (C) Copyright 2004
12 * esd gmbh <www.esd-electronics.com> 12 * esd gmbh <www.esd-electronics.com>
13 * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 13 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
14 * 14 *
15 * based on code from grub2 fs/ext2.c and fs/fshelp.c by 15 * based on code from grub2 fs/ext2.c and fs/fshelp.c by
16 * GRUB -- GRand Unified Bootloader 16 * GRUB -- GRand Unified Bootloader
17 * Copyright (C) 2003, 2004 Free Software Foundation, Inc. 17 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
18 * 18 *
19 * ext4write : Based on generic ext4 protocol. 19 * ext4write : Based on generic ext4 protocol.
20 * 20 *
21 * This program is free software; you can redistribute it and/or modify 21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by 22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or 23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version. 24 * (at your option) any later version.
25 * 25 *
26 * This program is distributed in the hope that it will be useful, 26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details. 29 * GNU General Public License for more details.
30 * 30 *
31 * You should have received a copy of the GNU General Public License 31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software 32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 33 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 */ 34 */
35 35
36 #include <common.h> 36 #include <common.h>
37 #include <ext_common.h> 37 #include <ext_common.h>
38 #include <ext4fs.h> 38 #include <ext4fs.h>
39 #include "ext4_common.h" 39 #include "ext4_common.h"
40 40
41 int ext4fs_symlinknest; 41 int ext4fs_symlinknest;
42 struct ext_filesystem ext_fs; 42 struct ext_filesystem ext_fs;
43 43
44 struct ext_filesystem *get_fs(void) 44 struct ext_filesystem *get_fs(void)
45 { 45 {
46 return &ext_fs; 46 return &ext_fs;
47 } 47 }
48 48
49 void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot) 49 void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot)
50 { 50 {
51 if ((node != &ext4fs_root->diropen) && (node != currroot)) 51 if ((node != &ext4fs_root->diropen) && (node != currroot))
52 free(node); 52 free(node);
53 } 53 }
54 54
55 /* 55 /*
56 * Taken from openmoko-kernel mailing list: By Andy green 56 * Taken from openmoko-kernel mailing list: By Andy green
57 * Optimized read file API : collects and defers contiguous sector 57 * Optimized read file API : collects and defers contiguous sector
58 * reads into one potentially more efficient larger sequential read action 58 * reads into one potentially more efficient larger sequential read action
59 */ 59 */
60 int ext4fs_read_file(struct ext2fs_node *node, int pos, 60 int ext4fs_read_file(struct ext2fs_node *node, int pos,
61 unsigned int len, char *buf) 61 unsigned int len, char *buf)
62 { 62 {
63 struct ext_filesystem *fs = get_fs(); 63 struct ext_filesystem *fs = get_fs();
64 int i; 64 int i;
65 int blockcnt; 65 lbaint_t blockcnt;
66 int log2blksz = fs->dev_desc->log2blksz; 66 int log2blksz = fs->dev_desc->log2blksz;
67 int log2_fs_blocksize = LOG2_BLOCK_SIZE(node->data) - log2blksz; 67 int log2_fs_blocksize = LOG2_BLOCK_SIZE(node->data) - log2blksz;
68 int blocksize = (1 << (log2_fs_blocksize + log2blksz)); 68 int blocksize = (1 << (log2_fs_blocksize + log2blksz));
69 unsigned int filesize = __le32_to_cpu(node->inode.size); 69 unsigned int filesize = __le32_to_cpu(node->inode.size);
70 int previous_block_number = -1; 70 lbaint_t previous_block_number = -1;
71 int delayed_start = 0; 71 lbaint_t delayed_start = 0;
72 int delayed_extent = 0; 72 lbaint_t delayed_extent = 0;
73 int delayed_skipfirst = 0; 73 lbaint_t delayed_skipfirst = 0;
74 int delayed_next = 0; 74 lbaint_t delayed_next = 0;
75 char *delayed_buf = NULL; 75 char *delayed_buf = NULL;
76 short status; 76 short status;
77 77
78 /* Adjust len so it we can't read past the end of the file. */ 78 /* Adjust len so it we can't read past the end of the file. */
79 if (len > filesize) 79 if (len > filesize)
80 len = filesize; 80 len = filesize;
81 81
82 blockcnt = ((len + pos) + blocksize - 1) / blocksize; 82 blockcnt = ((len + pos) + blocksize - 1) / blocksize;
83 83
84 for (i = pos / blocksize; i < blockcnt; i++) { 84 for (i = pos / blocksize; i < blockcnt; i++) {
85 int blknr; 85 lbaint_t blknr;
86 int blockoff = pos % blocksize; 86 int blockoff = pos % blocksize;
87 int blockend = blocksize; 87 int blockend = blocksize;
88 int skipfirst = 0; 88 int skipfirst = 0;
89 blknr = read_allocated_block(&(node->inode), i); 89 blknr = read_allocated_block(&(node->inode), i);
90 if (blknr < 0) 90 if (blknr < 0)
91 return -1; 91 return -1;
92 92
93 blknr = blknr << log2_fs_blocksize; 93 blknr = blknr << log2_fs_blocksize;
94 94
95 /* Last block. */ 95 /* Last block. */
96 if (i == blockcnt - 1) { 96 if (i == blockcnt - 1) {
97 blockend = (len + pos) % blocksize; 97 blockend = (len + pos) % blocksize;
98 98
99 /* The last portion is exactly blocksize. */ 99 /* The last portion is exactly blocksize. */
100 if (!blockend) 100 if (!blockend)
101 blockend = blocksize; 101 blockend = blocksize;
102 } 102 }
103 103
104 /* First block. */ 104 /* First block. */
105 if (i == pos / blocksize) { 105 if (i == pos / blocksize) {
106 skipfirst = blockoff; 106 skipfirst = blockoff;
107 blockend -= skipfirst; 107 blockend -= skipfirst;
108 } 108 }
109 if (blknr) { 109 if (blknr) {
110 int status; 110 int status;
111 111
112 if (previous_block_number != -1) { 112 if (previous_block_number != -1) {
113 if (delayed_next == blknr) { 113 if (delayed_next == blknr) {
114 delayed_extent += blockend; 114 delayed_extent += blockend;
115 delayed_next += blockend >> log2blksz; 115 delayed_next += blockend >> log2blksz;
116 } else { /* spill */ 116 } else { /* spill */
117 status = ext4fs_devread(delayed_start, 117 status = ext4fs_devread(delayed_start,
118 delayed_skipfirst, 118 delayed_skipfirst,
119 delayed_extent, 119 delayed_extent,
120 delayed_buf); 120 delayed_buf);
121 if (status == 0) 121 if (status == 0)
122 return -1; 122 return -1;
123 previous_block_number = blknr; 123 previous_block_number = blknr;
124 delayed_start = blknr; 124 delayed_start = blknr;
125 delayed_extent = blockend; 125 delayed_extent = blockend;
126 delayed_skipfirst = skipfirst; 126 delayed_skipfirst = skipfirst;
127 delayed_buf = buf; 127 delayed_buf = buf;
128 delayed_next = blknr + 128 delayed_next = blknr +
129 (blockend >> log2blksz); 129 (blockend >> log2blksz);
130 } 130 }
131 } else { 131 } else {
132 previous_block_number = blknr; 132 previous_block_number = blknr;
133 delayed_start = blknr; 133 delayed_start = blknr;
134 delayed_extent = blockend; 134 delayed_extent = blockend;
135 delayed_skipfirst = skipfirst; 135 delayed_skipfirst = skipfirst;
136 delayed_buf = buf; 136 delayed_buf = buf;
137 delayed_next = blknr + 137 delayed_next = blknr +
138 (blockend >> log2blksz); 138 (blockend >> log2blksz);
139 } 139 }
140 } else { 140 } else {
141 if (previous_block_number != -1) { 141 if (previous_block_number != -1) {
142 /* spill */ 142 /* spill */
143 status = ext4fs_devread(delayed_start, 143 status = ext4fs_devread(delayed_start,
144 delayed_skipfirst, 144 delayed_skipfirst,
145 delayed_extent, 145 delayed_extent,
146 delayed_buf); 146 delayed_buf);
147 if (status == 0) 147 if (status == 0)
148 return -1; 148 return -1;
149 previous_block_number = -1; 149 previous_block_number = -1;
150 } 150 }
151 memset(buf, 0, blocksize - skipfirst); 151 memset(buf, 0, blocksize - skipfirst);
152 } 152 }
153 buf += blocksize - skipfirst; 153 buf += blocksize - skipfirst;
154 } 154 }
155 if (previous_block_number != -1) { 155 if (previous_block_number != -1) {
156 /* spill */ 156 /* spill */
157 status = ext4fs_devread(delayed_start, 157 status = ext4fs_devread(delayed_start,
158 delayed_skipfirst, delayed_extent, 158 delayed_skipfirst, delayed_extent,
159 delayed_buf); 159 delayed_buf);
160 if (status == 0) 160 if (status == 0)
161 return -1; 161 return -1;
162 previous_block_number = -1; 162 previous_block_number = -1;
163 } 163 }
164 164
165 return len; 165 return len;
166 } 166 }
167 167
168 int ext4fs_ls(const char *dirname) 168 int ext4fs_ls(const char *dirname)
169 { 169 {
170 struct ext2fs_node *dirnode; 170 struct ext2fs_node *dirnode;
171 int status; 171 int status;
172 172
173 if (dirname == NULL) 173 if (dirname == NULL)
174 return 0; 174 return 0;
175 175
176 status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode, 176 status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode,
177 FILETYPE_DIRECTORY); 177 FILETYPE_DIRECTORY);
178 if (status != 1) { 178 if (status != 1) {
179 printf("** Can not find directory. **\n"); 179 printf("** Can not find directory. **\n");
180 return 1; 180 return 1;
181 } 181 }
182 182
183 ext4fs_iterate_dir(dirnode, NULL, NULL, NULL); 183 ext4fs_iterate_dir(dirnode, NULL, NULL, NULL);
184 ext4fs_free_node(dirnode, &ext4fs_root->diropen); 184 ext4fs_free_node(dirnode, &ext4fs_root->diropen);
185 185
186 return 0; 186 return 0;
187 } 187 }
188 188
189 int ext4fs_read(char *buf, unsigned len) 189 int ext4fs_read(char *buf, unsigned len)
190 { 190 {
191 if (ext4fs_root == NULL || ext4fs_file == NULL) 191 if (ext4fs_root == NULL || ext4fs_file == NULL)
192 return 0; 192 return 0;
193 193
194 return ext4fs_read_file(ext4fs_file, 0, len, buf); 194 return ext4fs_read_file(ext4fs_file, 0, len, buf);
195 } 195 }
196 196
197 int ext4fs_probe(block_dev_desc_t *fs_dev_desc, 197 int ext4fs_probe(block_dev_desc_t *fs_dev_desc,
198 disk_partition_t *fs_partition) 198 disk_partition_t *fs_partition)
199 { 199 {
200 ext4fs_set_blk_dev(fs_dev_desc, fs_partition); 200 ext4fs_set_blk_dev(fs_dev_desc, fs_partition);
201 201
202 if (!ext4fs_mount(fs_partition->size)) { 202 if (!ext4fs_mount(fs_partition->size)) {
203 ext4fs_close(); 203 ext4fs_close();
204 return -1; 204 return -1;
205 } 205 }
206 206
207 return 0; 207 return 0;
208 } 208 }
209 209
210 int ext4_read_file(const char *filename, void *buf, int offset, int len) 210 int ext4_read_file(const char *filename, void *buf, int offset, int len)
211 { 211 {
212 int file_len; 212 int file_len;
213 int len_read; 213 int len_read;
214 214
215 if (offset != 0) { 215 if (offset != 0) {
216 printf("** Cannot support non-zero offset **\n"); 216 printf("** Cannot support non-zero offset **\n");
217 return -1; 217 return -1;
218 } 218 }
219 219
220 file_len = ext4fs_open(filename); 220 file_len = ext4fs_open(filename);
221 if (file_len < 0) { 221 if (file_len < 0) {
222 printf("** File not found %s **\n", filename); 222 printf("** File not found %s **\n", filename);
223 return -1; 223 return -1;
224 } 224 }
225 225
226 if (len == 0) 226 if (len == 0)
227 len = file_len; 227 len = file_len;
228 228
229 len_read = ext4fs_read(buf, len); 229 len_read = ext4fs_read(buf, len);
230 230
231 return len_read; 231 return len_read;
232 } 232 }
233 233
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * Ext4 Extent data structures are taken from original ext4 fs code 7 * Ext4 Extent data structures are taken from original ext4 fs code
8 * as found in the linux kernel. 8 * as found in the linux kernel.
9 * 9 *
10 * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com 10 * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com
11 * Written by Alex Tomas <alex@clusterfs.com> 11 * Written by Alex Tomas <alex@clusterfs.com>
12 * 12 *
13 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as 14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
16 * 16 *
17 * This program is distributed in the hope that it will be useful, 17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details. 20 * GNU General Public License for more details.
21 * 21 *
22 * You should have received a copy of the GNU General Public License 22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software 23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */ 25 */
26 26
27 #ifndef __EXT4__ 27 #ifndef __EXT4__
28 #define __EXT4__ 28 #define __EXT4__
29 #include <ext_common.h> 29 #include <ext_common.h>
30 30
31 #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ 31 #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
32 #define EXT4_EXT_MAGIC 0xf30a 32 #define EXT4_EXT_MAGIC 0xf30a
33 #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 33 #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
34 #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 34 #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040
35 #define EXT4_INDIRECT_BLOCKS 12 35 #define EXT4_INDIRECT_BLOCKS 12
36 36
37 #define EXT4_BG_INODE_UNINIT 0x0001 37 #define EXT4_BG_INODE_UNINIT 0x0001
38 #define EXT4_BG_BLOCK_UNINIT 0x0002 38 #define EXT4_BG_BLOCK_UNINIT 0x0002
39 #define EXT4_BG_INODE_ZEROED 0x0004 39 #define EXT4_BG_INODE_ZEROED 0x0004
40 40
41 /* 41 /*
42 * ext4_inode has i_block array (60 bytes total). 42 * ext4_inode has i_block array (60 bytes total).
43 * The first 12 bytes store ext4_extent_header; 43 * The first 12 bytes store ext4_extent_header;
44 * the remainder stores an array of ext4_extent. 44 * the remainder stores an array of ext4_extent.
45 */ 45 */
46 46
47 /* 47 /*
48 * This is the extent on-disk structure. 48 * This is the extent on-disk structure.
49 * It's used at the bottom of the tree. 49 * It's used at the bottom of the tree.
50 */ 50 */
51 struct ext4_extent { 51 struct ext4_extent {
52 __le32 ee_block; /* first logical block extent covers */ 52 __le32 ee_block; /* first logical block extent covers */
53 __le16 ee_len; /* number of blocks covered by extent */ 53 __le16 ee_len; /* number of blocks covered by extent */
54 __le16 ee_start_hi; /* high 16 bits of physical block */ 54 __le16 ee_start_hi; /* high 16 bits of physical block */
55 __le32 ee_start_lo; /* low 32 bits of physical block */ 55 __le32 ee_start_lo; /* low 32 bits of physical block */
56 }; 56 };
57 57
58 /* 58 /*
59 * This is index on-disk structure. 59 * This is index on-disk structure.
60 * It's used at all the levels except the bottom. 60 * It's used at all the levels except the bottom.
61 */ 61 */
62 struct ext4_extent_idx { 62 struct ext4_extent_idx {
63 __le32 ei_block; /* index covers logical blocks from 'block' */ 63 __le32 ei_block; /* index covers logical blocks from 'block' */
64 __le32 ei_leaf_lo; /* pointer to the physical block of the next * 64 __le32 ei_leaf_lo; /* pointer to the physical block of the next *
65 * level. leaf or next index could be there */ 65 * level. leaf or next index could be there */
66 __le16 ei_leaf_hi; /* high 16 bits of physical block */ 66 __le16 ei_leaf_hi; /* high 16 bits of physical block */
67 __u16 ei_unused; 67 __u16 ei_unused;
68 }; 68 };
69 69
70 /* Each block (leaves and indexes), even inode-stored has header. */ 70 /* Each block (leaves and indexes), even inode-stored has header. */
71 struct ext4_extent_header { 71 struct ext4_extent_header {
72 __le16 eh_magic; /* probably will support different formats */ 72 __le16 eh_magic; /* probably will support different formats */
73 __le16 eh_entries; /* number of valid entries */ 73 __le16 eh_entries; /* number of valid entries */
74 __le16 eh_max; /* capacity of store in entries */ 74 __le16 eh_max; /* capacity of store in entries */
75 __le16 eh_depth; /* has tree real underlying blocks? */ 75 __le16 eh_depth; /* has tree real underlying blocks? */
76 __le32 eh_generation; /* generation of the tree */ 76 __le32 eh_generation; /* generation of the tree */
77 }; 77 };
78 78
79 struct ext_filesystem { 79 struct ext_filesystem {
80 /* Total Sector of partition */ 80 /* Total Sector of partition */
81 uint64_t total_sect; 81 uint64_t total_sect;
82 /* Block size of partition */ 82 /* Block size of partition */
83 uint32_t blksz; 83 uint32_t blksz;
84 /* Inode size of partition */ 84 /* Inode size of partition */
85 uint32_t inodesz; 85 uint32_t inodesz;
86 /* Sectors per Block */ 86 /* Sectors per Block */
87 uint32_t sect_perblk; 87 uint32_t sect_perblk;
88 /* Group Descriptor Block Number */ 88 /* Group Descriptor Block Number */
89 uint32_t gdtable_blkno; 89 uint32_t gdtable_blkno;
90 /* Total block groups of partition */ 90 /* Total block groups of partition */
91 uint32_t no_blkgrp; 91 uint32_t no_blkgrp;
92 /* No of blocks required for bgdtable */ 92 /* No of blocks required for bgdtable */
93 uint32_t no_blk_pergdt; 93 uint32_t no_blk_pergdt;
94 /* Superblock */ 94 /* Superblock */
95 struct ext2_sblock *sb; 95 struct ext2_sblock *sb;
96 /* Block group descritpor table */ 96 /* Block group descritpor table */
97 struct ext2_block_group *bgd; 97 struct ext2_block_group *bgd;
98 char *gdtable; 98 char *gdtable;
99 99
100 /* Block Bitmap Related */ 100 /* Block Bitmap Related */
101 unsigned char **blk_bmaps; 101 unsigned char **blk_bmaps;
102 long int curr_blkno; 102 long int curr_blkno;
103 uint16_t first_pass_bbmap; 103 uint16_t first_pass_bbmap;
104 104
105 /* Inode Bitmap Related */ 105 /* Inode Bitmap Related */
106 unsigned char **inode_bmaps; 106 unsigned char **inode_bmaps;
107 int curr_inode_no; 107 int curr_inode_no;
108 uint16_t first_pass_ibmap; 108 uint16_t first_pass_ibmap;
109 109
110 /* Journal Related */ 110 /* Journal Related */
111 111
112 /* Block Device Descriptor */ 112 /* Block Device Descriptor */
113 block_dev_desc_t *dev_desc; 113 block_dev_desc_t *dev_desc;
114 }; 114 };
115 115
116 extern struct ext2_data *ext4fs_root; 116 extern struct ext2_data *ext4fs_root;
117 extern struct ext2fs_node *ext4fs_file; 117 extern struct ext2fs_node *ext4fs_file;
118 118
119 #if defined(CONFIG_EXT4_WRITE) 119 #if defined(CONFIG_EXT4_WRITE)
120 extern struct ext2_inode *g_parent_inode; 120 extern struct ext2_inode *g_parent_inode;
121 extern int gd_index; 121 extern int gd_index;
122 extern int gindex; 122 extern int gindex;
123 123
124 int ext4fs_init(void); 124 int ext4fs_init(void);
125 void ext4fs_deinit(void); 125 void ext4fs_deinit(void);
126 int ext4fs_filename_check(char *filename); 126 int ext4fs_filename_check(char *filename);
127 int ext4fs_write(const char *fname, unsigned char *buffer, 127 int ext4fs_write(const char *fname, unsigned char *buffer,
128 unsigned long sizebytes); 128 unsigned long sizebytes);
129 #endif 129 #endif
130 130
131 struct ext_filesystem *get_fs(void); 131 struct ext_filesystem *get_fs(void);
132 int ext4fs_open(const char *filename); 132 int ext4fs_open(const char *filename);
133 int ext4fs_read(char *buf, unsigned len); 133 int ext4fs_read(char *buf, unsigned len);
134 int ext4fs_mount(unsigned part_length); 134 int ext4fs_mount(unsigned part_length);
135 void ext4fs_close(void); 135 void ext4fs_close(void);
136 int ext4fs_ls(const char *dirname); 136 int ext4fs_ls(const char *dirname);
137 void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot); 137 void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot);
138 int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf); 138 int ext4fs_devread(lbaint_t sector, int byte_offset, int byte_len, char *buf);
139 void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info); 139 void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info);
140 long int read_allocated_block(struct ext2_inode *inode, int fileblock); 140 long int read_allocated_block(struct ext2_inode *inode, int fileblock);
141 int ext4fs_probe(block_dev_desc_t *fs_dev_desc, 141 int ext4fs_probe(block_dev_desc_t *fs_dev_desc,
142 disk_partition_t *fs_partition); 142 disk_partition_t *fs_partition);
143 int ext4_read_file(const char *filename, void *buf, int offset, int len); 143 int ext4_read_file(const char *filename, void *buf, int offset, int len);
144 int ext4_read_superblock(char *buffer); 144 int ext4_read_superblock(char *buffer);
145 #endif 145 #endif
146 146
include/ext_common.h
1 /* 1 /*
2 * (C) Copyright 2011 - 2012 Samsung Electronics 2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by 3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com> 4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com> 5 * Manjunatha C Achar <a.manjunatha@samsung.com>
6 * 6 *
7 * Data structures and headers for ext4 support have been taken from 7 * Data structures and headers for ext4 support have been taken from
8 * ext2 ls load support in Uboot 8 * ext2 ls load support in Uboot
9 * 9 *
10 * (C) Copyright 2004 10 * (C) Copyright 2004
11 * esd gmbh <www.esd-electronics.com> 11 * esd gmbh <www.esd-electronics.com>
12 * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 12 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
13 * 13 *
14 * based on code from grub2 fs/ext2.c and fs/fshelp.c by 14 * based on code from grub2 fs/ext2.c and fs/fshelp.c by
15 * GRUB -- GRand Unified Bootloader 15 * GRUB -- GRand Unified Bootloader
16 * Copyright (C) 2003, 2004 Free Software Foundation, Inc. 16 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
17 * 17 *
18 * This program is free software; you can redistribute it and/or modify 18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by 19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or 20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version. 21 * (at your option) any later version.
22 * 22 *
23 * This program is distributed in the hope that it will be useful, 23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details. 26 * GNU General Public License for more details.
27 * 27 *
28 * You should have received a copy of the GNU General Public License 28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software 29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 */ 31 */
32 32
33 #ifndef __EXT_COMMON__ 33 #ifndef __EXT_COMMON__
34 #define __EXT_COMMON__ 34 #define __EXT_COMMON__
35 #include <command.h> 35 #include <command.h>
36 #define SECTOR_SIZE 0x200 36 #define SECTOR_SIZE 0x200
37 37
38 /* Magic value used to identify an ext2 filesystem. */ 38 /* Magic value used to identify an ext2 filesystem. */
39 #define EXT2_MAGIC 0xEF53 39 #define EXT2_MAGIC 0xEF53
40 /* Amount of indirect blocks in an inode. */ 40 /* Amount of indirect blocks in an inode. */
41 #define INDIRECT_BLOCKS 12 41 #define INDIRECT_BLOCKS 12
42 /* Maximum lenght of a pathname. */ 42 /* Maximum lenght of a pathname. */
43 #define EXT2_PATH_MAX 4096 43 #define EXT2_PATH_MAX 4096
44 /* Maximum nesting of symlinks, used to prevent a loop. */ 44 /* Maximum nesting of symlinks, used to prevent a loop. */
45 #define EXT2_MAX_SYMLINKCNT 8 45 #define EXT2_MAX_SYMLINKCNT 8
46 46
47 /* Filetype used in directory entry. */ 47 /* Filetype used in directory entry. */
48 #define FILETYPE_UNKNOWN 0 48 #define FILETYPE_UNKNOWN 0
49 #define FILETYPE_REG 1 49 #define FILETYPE_REG 1
50 #define FILETYPE_DIRECTORY 2 50 #define FILETYPE_DIRECTORY 2
51 #define FILETYPE_SYMLINK 7 51 #define FILETYPE_SYMLINK 7
52 52
53 /* Filetype information as used in inodes. */ 53 /* Filetype information as used in inodes. */
54 #define FILETYPE_INO_MASK 0170000 54 #define FILETYPE_INO_MASK 0170000
55 #define FILETYPE_INO_REG 0100000 55 #define FILETYPE_INO_REG 0100000
56 #define FILETYPE_INO_DIRECTORY 0040000 56 #define FILETYPE_INO_DIRECTORY 0040000
57 #define FILETYPE_INO_SYMLINK 0120000 57 #define FILETYPE_INO_SYMLINK 0120000
58 #define EXT2_ROOT_INO 2 /* Root inode */ 58 #define EXT2_ROOT_INO 2 /* Root inode */
59 59
60 /* The size of an ext2 block in bytes. */ 60 /* The size of an ext2 block in bytes. */
61 #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data)) 61 #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
62 62
63 /* Log2 size of ext2 block in bytes. */ 63 /* Log2 size of ext2 block in bytes. */
64 #define LOG2_BLOCK_SIZE(data) (__le32_to_cpu \ 64 #define LOG2_BLOCK_SIZE(data) (__le32_to_cpu \
65 (data->sblock.log2_block_size) \ 65 (data->sblock.log2_block_size) \
66 + EXT2_MIN_BLOCK_LOG_SIZE) 66 + EXT2_MIN_BLOCK_LOG_SIZE)
67 #define INODE_SIZE_FILESYSTEM(data) (__le32_to_cpu \ 67 #define INODE_SIZE_FILESYSTEM(data) (__le32_to_cpu \
68 (data->sblock.inode_size)) 68 (data->sblock.inode_size))
69 69
70 #define EXT2_FT_DIR 2 70 #define EXT2_FT_DIR 2
71 #define SUCCESS 1 71 #define SUCCESS 1
72 72
73 /* Macro-instructions used to manage several block sizes */ 73 /* Macro-instructions used to manage several block sizes */
74 #define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ 74 #define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
75 #define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */ 75 #define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
76 #define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) 76 #define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
77 #define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) 77 #define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
78 78
79 /* The ext2 superblock. */ 79 /* The ext2 superblock. */
80 struct ext2_sblock { 80 struct ext2_sblock {
81 uint32_t total_inodes; 81 uint32_t total_inodes;
82 uint32_t total_blocks; 82 uint32_t total_blocks;
83 uint32_t reserved_blocks; 83 uint32_t reserved_blocks;
84 uint32_t free_blocks; 84 uint32_t free_blocks;
85 uint32_t free_inodes; 85 uint32_t free_inodes;
86 uint32_t first_data_block; 86 uint32_t first_data_block;
87 uint32_t log2_block_size; 87 uint32_t log2_block_size;
88 uint32_t log2_fragment_size; 88 uint32_t log2_fragment_size;
89 uint32_t blocks_per_group; 89 uint32_t blocks_per_group;
90 uint32_t fragments_per_group; 90 uint32_t fragments_per_group;
91 uint32_t inodes_per_group; 91 uint32_t inodes_per_group;
92 uint32_t mtime; 92 uint32_t mtime;
93 uint32_t utime; 93 uint32_t utime;
94 uint16_t mnt_count; 94 uint16_t mnt_count;
95 uint16_t max_mnt_count; 95 uint16_t max_mnt_count;
96 uint16_t magic; 96 uint16_t magic;
97 uint16_t fs_state; 97 uint16_t fs_state;
98 uint16_t error_handling; 98 uint16_t error_handling;
99 uint16_t minor_revision_level; 99 uint16_t minor_revision_level;
100 uint32_t lastcheck; 100 uint32_t lastcheck;
101 uint32_t checkinterval; 101 uint32_t checkinterval;
102 uint32_t creator_os; 102 uint32_t creator_os;
103 uint32_t revision_level; 103 uint32_t revision_level;
104 uint16_t uid_reserved; 104 uint16_t uid_reserved;
105 uint16_t gid_reserved; 105 uint16_t gid_reserved;
106 uint32_t first_inode; 106 uint32_t first_inode;
107 uint16_t inode_size; 107 uint16_t inode_size;
108 uint16_t block_group_number; 108 uint16_t block_group_number;
109 uint32_t feature_compatibility; 109 uint32_t feature_compatibility;
110 uint32_t feature_incompat; 110 uint32_t feature_incompat;
111 uint32_t feature_ro_compat; 111 uint32_t feature_ro_compat;
112 uint32_t unique_id[4]; 112 uint32_t unique_id[4];
113 char volume_name[16]; 113 char volume_name[16];
114 char last_mounted_on[64]; 114 char last_mounted_on[64];
115 uint32_t compression_info; 115 uint32_t compression_info;
116 }; 116 };
117 117
118 struct ext2_block_group { 118 struct ext2_block_group {
119 __u32 block_id; /* Blocks bitmap block */ 119 __u32 block_id; /* Blocks bitmap block */
120 __u32 inode_id; /* Inodes bitmap block */ 120 __u32 inode_id; /* Inodes bitmap block */
121 __u32 inode_table_id; /* Inodes table block */ 121 __u32 inode_table_id; /* Inodes table block */
122 __u16 free_blocks; /* Free blocks count */ 122 __u16 free_blocks; /* Free blocks count */
123 __u16 free_inodes; /* Free inodes count */ 123 __u16 free_inodes; /* Free inodes count */
124 __u16 used_dir_cnt; /* Directories count */ 124 __u16 used_dir_cnt; /* Directories count */
125 __u16 bg_flags; 125 __u16 bg_flags;
126 __u32 bg_reserved[2]; 126 __u32 bg_reserved[2];
127 __u16 bg_itable_unused; /* Unused inodes count */ 127 __u16 bg_itable_unused; /* Unused inodes count */
128 __u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/ 128 __u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/
129 }; 129 };
130 130
131 /* The ext2 inode. */ 131 /* The ext2 inode. */
132 struct ext2_inode { 132 struct ext2_inode {
133 uint16_t mode; 133 uint16_t mode;
134 uint16_t uid; 134 uint16_t uid;
135 uint32_t size; 135 uint32_t size;
136 uint32_t atime; 136 uint32_t atime;
137 uint32_t ctime; 137 uint32_t ctime;
138 uint32_t mtime; 138 uint32_t mtime;
139 uint32_t dtime; 139 uint32_t dtime;
140 uint16_t gid; 140 uint16_t gid;
141 uint16_t nlinks; 141 uint16_t nlinks;
142 uint32_t blockcnt; /* Blocks of 512 bytes!! */ 142 uint32_t blockcnt; /* Blocks of 512 bytes!! */
143 uint32_t flags; 143 uint32_t flags;
144 uint32_t osd1; 144 uint32_t osd1;
145 union { 145 union {
146 struct datablocks { 146 struct datablocks {
147 uint32_t dir_blocks[INDIRECT_BLOCKS]; 147 uint32_t dir_blocks[INDIRECT_BLOCKS];
148 uint32_t indir_block; 148 uint32_t indir_block;
149 uint32_t double_indir_block; 149 uint32_t double_indir_block;
150 uint32_t triple_indir_block; 150 uint32_t triple_indir_block;
151 } blocks; 151 } blocks;
152 char symlink[60]; 152 char symlink[60];
153 } b; 153 } b;
154 uint32_t version; 154 uint32_t version;
155 uint32_t acl; 155 uint32_t acl;
156 uint32_t dir_acl; 156 uint32_t dir_acl;
157 uint32_t fragment_addr; 157 uint32_t fragment_addr;
158 uint32_t osd2[3]; 158 uint32_t osd2[3];
159 }; 159 };
160 160
161 /* The header of an ext2 directory entry. */ 161 /* The header of an ext2 directory entry. */
162 struct ext2_dirent { 162 struct ext2_dirent {
163 uint32_t inode; 163 uint32_t inode;
164 uint16_t direntlen; 164 uint16_t direntlen;
165 uint8_t namelen; 165 uint8_t namelen;
166 uint8_t filetype; 166 uint8_t filetype;
167 }; 167 };
168 168
169 struct ext2fs_node { 169 struct ext2fs_node {
170 struct ext2_data *data; 170 struct ext2_data *data;
171 struct ext2_inode inode; 171 struct ext2_inode inode;
172 int ino; 172 int ino;
173 int inode_read; 173 int inode_read;
174 }; 174 };
175 175
176 /* Information about a "mounted" ext2 filesystem. */ 176 /* Information about a "mounted" ext2 filesystem. */
177 struct ext2_data { 177 struct ext2_data {
178 struct ext2_sblock sblock; 178 struct ext2_sblock sblock;
179 struct ext2_inode *inode; 179 struct ext2_inode *inode;
180 struct ext2fs_node diropen; 180 struct ext2fs_node diropen;
181 }; 181 };
182 182
183 extern unsigned long part_offset; 183 extern lbaint_t part_offset;
184 184
185 int do_ext2ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); 185 int do_ext2ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
186 int do_ext2load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); 186 int do_ext2load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
187 int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc, 187 int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc,
188 char *const argv[]); 188 char *const argv[]);
189 int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); 189 int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
190 int do_ext4_write(cmd_tbl_t *cmdtp, int flag, int argc, 190 int do_ext4_write(cmd_tbl_t *cmdtp, int flag, int argc,
191 char *const argv[]); 191 char *const argv[]);
192 #endif 192 #endif
193 193
1 /* 1 /*
2 * (C) Copyright 2000 2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 * 4 *
5 * See file CREDITS for list of people who contributed to this 5 * See file CREDITS for list of people who contributed to this
6 * project. 6 * project.
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of 10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version. 11 * the License, or (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA 21 * MA 02111-1307 USA
22 */ 22 */
23 23
24 #ifndef _IDE_H 24 #ifndef _IDE_H
25 #define _IDE_H 25 #define _IDE_H
26 26
27 #define IDE_BUS(dev) (dev / (CONFIG_SYS_IDE_MAXDEVICE / CONFIG_SYS_IDE_MAXBUS)) 27 #define IDE_BUS(dev) (dev / (CONFIG_SYS_IDE_MAXDEVICE / CONFIG_SYS_IDE_MAXBUS))
28 28
29 #define ATA_CURR_BASE(dev) (CONFIG_SYS_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)]) 29 #define ATA_CURR_BASE(dev) (CONFIG_SYS_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)])
30 extern ulong ide_bus_offset[]; 30 extern ulong ide_bus_offset[];
31 31
32 #ifdef CONFIG_IDE_LED 32 #ifdef CONFIG_IDE_LED
33 33
34 /* 34 /*
35 * LED Port 35 * LED Port
36 */ 36 */
37 #define LED_PORT ((uchar *)(PER8_BASE + 0x3000)) 37 #define LED_PORT ((uchar *)(PER8_BASE + 0x3000))
38 #define LED_IDE1 0x01 38 #define LED_IDE1 0x01
39 #define LED_IDE2 0x02 39 #define LED_IDE2 0x02
40 #define DEVICE_LED(d) ((d & 2) | ((d & 2) == 0)) /* depends on bit positions! */ 40 #define DEVICE_LED(d) ((d & 2) | ((d & 2) == 0)) /* depends on bit positions! */
41 41
42 #endif /* CONFIG_IDE_LED */ 42 #endif /* CONFIG_IDE_LED */
43 43
44 #ifdef CONFIG_SYS_64BIT_LBA 44 #ifdef CONFIG_SYS_64BIT_LBA
45 typedef uint64_t lbaint_t; 45 typedef uint64_t lbaint_t;
46 #define LBAF "%llx" 46 #define LBAF "%llx"
47 #define LBAFU "%llu"
47 #else 48 #else
48 typedef ulong lbaint_t; 49 typedef ulong lbaint_t;
49 #define LBAF "%lx" 50 #define LBAF "%lx"
51 #define LBAFU "%lu"
50 #endif 52 #endif
51 53
52 /* 54 /*
53 * Function Prototypes 55 * Function Prototypes
54 */ 56 */
55 57
56 void ide_init(void); 58 void ide_init(void);
57 ulong ide_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer); 59 ulong ide_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer);
58 ulong ide_write(int device, lbaint_t blknr, lbaint_t blkcnt, 60 ulong ide_write(int device, lbaint_t blknr, lbaint_t blkcnt,
59 const void *buffer); 61 const void *buffer);
60 62
61 #ifdef CONFIG_IDE_PREINIT 63 #ifdef CONFIG_IDE_PREINIT
62 int ide_preinit(void); 64 int ide_preinit(void);
63 #endif 65 #endif
64 66
65 #ifdef CONFIG_IDE_INIT_POSTRESET 67 #ifdef CONFIG_IDE_INIT_POSTRESET
66 int ide_init_postreset(void); 68 int ide_init_postreset(void);
67 #endif 69 #endif
68 70
69 #if defined(CONFIG_OF_IDE_FIXUP) 71 #if defined(CONFIG_OF_IDE_FIXUP)
70 int ide_device_present(int dev); 72 int ide_device_present(int dev);
71 #endif 73 #endif
72 74
73 #if defined(CONFIG_IDE_AHB) 75 #if defined(CONFIG_IDE_AHB)
74 unsigned char ide_read_register(int dev, unsigned int port); 76 unsigned char ide_read_register(int dev, unsigned int port);
75 void ide_write_register(int dev, unsigned int port, unsigned char val); 77 void ide_write_register(int dev, unsigned int port, unsigned char val);
76 void ide_read_data(int dev, ulong *sect_buf, int words); 78 void ide_read_data(int dev, ulong *sect_buf, int words);
77 void ide_write_data(int dev, ulong *sect_buf, int words); 79 void ide_write_data(int dev, ulong *sect_buf, int words);
78 #endif 80 #endif
79 81
80 /* 82 /*
81 * I/O function overrides 83 * I/O function overrides
82 */ 84 */
83 void ide_input_swap_data(int dev, ulong *sect_buf, int words); 85 void ide_input_swap_data(int dev, ulong *sect_buf, int words);
84 void ide_input_data(int dev, ulong *sect_buf, int words); 86 void ide_input_data(int dev, ulong *sect_buf, int words);
85 void ide_output_data(int dev, const ulong *sect_buf, int words); 87 void ide_output_data(int dev, const ulong *sect_buf, int words);
86 void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts); 88 void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts);
87 void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts); 89 void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts);
88 90
89 /** 91 /**
90 * board_start_ide() - Start up the board IDE interfac 92 * board_start_ide() - Start up the board IDE interfac
91 * 93 *
92 * @return 0 if ok 94 * @return 0 if ok
93 */ 95 */
94 int board_start_ide(void); 96 int board_start_ide(void);
95 97
96 #endif /* _IDE_H */ 98 #endif /* _IDE_H */
97 99
1 /* 1 /*
2 * (C) Copyright 2000-2004 2 * (C) Copyright 2000-2004
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 * 4 *
5 * See file CREDITS for list of people who contributed to this 5 * See file CREDITS for list of people who contributed to this
6 * project. 6 * project.
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of 10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version. 11 * the License, or (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA 21 * MA 02111-1307 USA
22 */ 22 */
23 #ifndef _PART_H 23 #ifndef _PART_H
24 #define _PART_H 24 #define _PART_H
25 25
26 #include <ide.h> 26 #include <ide.h>
27 27
28 typedef struct block_dev_desc { 28 typedef struct block_dev_desc {
29 int if_type; /* type of the interface */ 29 int if_type; /* type of the interface */
30 int dev; /* device number */ 30 int dev; /* device number */
31 unsigned char part_type; /* partition type */ 31 unsigned char part_type; /* partition type */
32 unsigned char target; /* target SCSI ID */ 32 unsigned char target; /* target SCSI ID */
33 unsigned char lun; /* target LUN */ 33 unsigned char lun; /* target LUN */
34 unsigned char type; /* device type */ 34 unsigned char type; /* device type */
35 unsigned char removable; /* removable device */ 35 unsigned char removable; /* removable device */
36 #ifdef CONFIG_LBA48 36 #ifdef CONFIG_LBA48
37 unsigned char lba48; /* device can use 48bit addr (ATA/ATAPI v7) */ 37 unsigned char lba48; /* device can use 48bit addr (ATA/ATAPI v7) */
38 #endif 38 #endif
39 lbaint_t lba; /* number of blocks */ 39 lbaint_t lba; /* number of blocks */
40 unsigned long blksz; /* block size */ 40 unsigned long blksz; /* block size */
41 int log2blksz; /* for convenience: log2(blksz) */ 41 int log2blksz; /* for convenience: log2(blksz) */
42 char vendor [40+1]; /* IDE model, SCSI Vendor */ 42 char vendor [40+1]; /* IDE model, SCSI Vendor */
43 char product[20+1]; /* IDE Serial no, SCSI product */ 43 char product[20+1]; /* IDE Serial no, SCSI product */
44 char revision[8+1]; /* firmware revision */ 44 char revision[8+1]; /* firmware revision */
45 unsigned long (*block_read)(int dev, 45 unsigned long (*block_read)(int dev,
46 lbaint_t start, 46 lbaint_t start,
47 lbaint_t blkcnt, 47 lbaint_t blkcnt,
48 void *buffer); 48 void *buffer);
49 unsigned long (*block_write)(int dev, 49 unsigned long (*block_write)(int dev,
50 lbaint_t start, 50 lbaint_t start,
51 lbaint_t blkcnt, 51 lbaint_t blkcnt,
52 const void *buffer); 52 const void *buffer);
53 unsigned long (*block_erase)(int dev, 53 unsigned long (*block_erase)(int dev,
54 lbaint_t start, 54 lbaint_t start,
55 lbaint_t blkcnt); 55 lbaint_t blkcnt);
56 void *priv; /* driver private struct pointer */ 56 void *priv; /* driver private struct pointer */
57 }block_dev_desc_t; 57 }block_dev_desc_t;
58 58
59 #define BLOCK_CNT(size, block_dev_desc) (PAD_COUNT(size, block_dev_desc->blksz)) 59 #define BLOCK_CNT(size, block_dev_desc) (PAD_COUNT(size, block_dev_desc->blksz))
60 #define PAD_TO_BLOCKSIZE(size, block_dev_desc) \ 60 #define PAD_TO_BLOCKSIZE(size, block_dev_desc) \
61 (PAD_SIZE(size, block_dev_desc->blksz)) 61 (PAD_SIZE(size, block_dev_desc->blksz))
62 #define LOG2(x) (((x & 0xaaaaaaaa) ? 1 : 0) + ((x & 0xcccccccc) ? 2 : 0) + \ 62 #define LOG2(x) (((x & 0xaaaaaaaa) ? 1 : 0) + ((x & 0xcccccccc) ? 2 : 0) + \
63 ((x & 0xf0f0f0f0) ? 4 : 0) + ((x & 0xff00ff00) ? 8 : 0) + \ 63 ((x & 0xf0f0f0f0) ? 4 : 0) + ((x & 0xff00ff00) ? 8 : 0) + \
64 ((x & 0xffff0000) ? 16 : 0)) 64 ((x & 0xffff0000) ? 16 : 0))
65 #define LOG2_INVALID(type) ((type)((sizeof(type)<<3)-1)) 65 #define LOG2_INVALID(type) ((type)((sizeof(type)<<3)-1))
66 66
67 /* Interface types: */ 67 /* Interface types: */
68 #define IF_TYPE_UNKNOWN 0 68 #define IF_TYPE_UNKNOWN 0
69 #define IF_TYPE_IDE 1 69 #define IF_TYPE_IDE 1
70 #define IF_TYPE_SCSI 2 70 #define IF_TYPE_SCSI 2
71 #define IF_TYPE_ATAPI 3 71 #define IF_TYPE_ATAPI 3
72 #define IF_TYPE_USB 4 72 #define IF_TYPE_USB 4
73 #define IF_TYPE_DOC 5 73 #define IF_TYPE_DOC 5
74 #define IF_TYPE_MMC 6 74 #define IF_TYPE_MMC 6
75 #define IF_TYPE_SD 7 75 #define IF_TYPE_SD 7
76 #define IF_TYPE_SATA 8 76 #define IF_TYPE_SATA 8
77 77
78 /* Part types */ 78 /* Part types */
79 #define PART_TYPE_UNKNOWN 0x00 79 #define PART_TYPE_UNKNOWN 0x00
80 #define PART_TYPE_MAC 0x01 80 #define PART_TYPE_MAC 0x01
81 #define PART_TYPE_DOS 0x02 81 #define PART_TYPE_DOS 0x02
82 #define PART_TYPE_ISO 0x03 82 #define PART_TYPE_ISO 0x03
83 #define PART_TYPE_AMIGA 0x04 83 #define PART_TYPE_AMIGA 0x04
84 #define PART_TYPE_EFI 0x05 84 #define PART_TYPE_EFI 0x05
85 85
86 /* 86 /*
87 * Type string for U-Boot bootable partitions 87 * Type string for U-Boot bootable partitions
88 */ 88 */
89 #define BOOT_PART_TYPE "U-Boot" /* primary boot partition type */ 89 #define BOOT_PART_TYPE "U-Boot" /* primary boot partition type */
90 #define BOOT_PART_COMP "PPCBoot" /* PPCBoot compatibility type */ 90 #define BOOT_PART_COMP "PPCBoot" /* PPCBoot compatibility type */
91 91
92 /* device types */ 92 /* device types */
93 #define DEV_TYPE_UNKNOWN 0xff /* not connected */ 93 #define DEV_TYPE_UNKNOWN 0xff /* not connected */
94 #define DEV_TYPE_HARDDISK 0x00 /* harddisk */ 94 #define DEV_TYPE_HARDDISK 0x00 /* harddisk */
95 #define DEV_TYPE_TAPE 0x01 /* Tape */ 95 #define DEV_TYPE_TAPE 0x01 /* Tape */
96 #define DEV_TYPE_CDROM 0x05 /* CD-ROM */ 96 #define DEV_TYPE_CDROM 0x05 /* CD-ROM */
97 #define DEV_TYPE_OPDISK 0x07 /* optical disk */ 97 #define DEV_TYPE_OPDISK 0x07 /* optical disk */
98 98
99 typedef struct disk_partition { 99 typedef struct disk_partition {
100 ulong start; /* # of first block in partition */ 100 lbaint_t start; /* # of first block in partition */
101 ulong size; /* number of blocks in partition */ 101 lbaint_t size; /* number of blocks in partition */
102 ulong blksz; /* block size in bytes */ 102 ulong blksz; /* block size in bytes */
103 uchar name[32]; /* partition name */ 103 uchar name[32]; /* partition name */
104 uchar type[32]; /* string type description */ 104 uchar type[32]; /* string type description */
105 int bootable; /* Active/Bootable flag is set */ 105 int bootable; /* Active/Bootable flag is set */
106 #ifdef CONFIG_PARTITION_UUIDS 106 #ifdef CONFIG_PARTITION_UUIDS
107 char uuid[37]; /* filesystem UUID as string, if exists */ 107 char uuid[37]; /* filesystem UUID as string, if exists */
108 #endif 108 #endif
109 } disk_partition_t; 109 } disk_partition_t;
110 110
111 /* Misc _get_dev functions */ 111 /* Misc _get_dev functions */
112 #ifdef CONFIG_PARTITIONS 112 #ifdef CONFIG_PARTITIONS
113 block_dev_desc_t *get_dev(const char *ifname, int dev); 113 block_dev_desc_t *get_dev(const char *ifname, int dev);
114 block_dev_desc_t* ide_get_dev(int dev); 114 block_dev_desc_t* ide_get_dev(int dev);
115 block_dev_desc_t* sata_get_dev(int dev); 115 block_dev_desc_t* sata_get_dev(int dev);
116 block_dev_desc_t* scsi_get_dev(int dev); 116 block_dev_desc_t* scsi_get_dev(int dev);
117 block_dev_desc_t* usb_stor_get_dev(int dev); 117 block_dev_desc_t* usb_stor_get_dev(int dev);
118 block_dev_desc_t* mmc_get_dev(int dev); 118 block_dev_desc_t* mmc_get_dev(int dev);
119 block_dev_desc_t* systemace_get_dev(int dev); 119 block_dev_desc_t* systemace_get_dev(int dev);
120 block_dev_desc_t* mg_disk_get_dev(int dev); 120 block_dev_desc_t* mg_disk_get_dev(int dev);
121 121
122 /* disk/part.c */ 122 /* disk/part.c */
123 int get_partition_info (block_dev_desc_t * dev_desc, int part, disk_partition_t *info); 123 int get_partition_info (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
124 void print_part (block_dev_desc_t *dev_desc); 124 void print_part (block_dev_desc_t *dev_desc);
125 void init_part (block_dev_desc_t *dev_desc); 125 void init_part (block_dev_desc_t *dev_desc);
126 void dev_print(block_dev_desc_t *dev_desc); 126 void dev_print(block_dev_desc_t *dev_desc);
127 int get_device(const char *ifname, const char *dev_str, 127 int get_device(const char *ifname, const char *dev_str,
128 block_dev_desc_t **dev_desc); 128 block_dev_desc_t **dev_desc);
129 int get_device_and_partition(const char *ifname, const char *dev_part_str, 129 int get_device_and_partition(const char *ifname, const char *dev_part_str,
130 block_dev_desc_t **dev_desc, 130 block_dev_desc_t **dev_desc,
131 disk_partition_t *info, int allow_whole_dev); 131 disk_partition_t *info, int allow_whole_dev);
132 #else 132 #else
133 static inline block_dev_desc_t *get_dev(const char *ifname, int dev) 133 static inline block_dev_desc_t *get_dev(const char *ifname, int dev)
134 { return NULL; } 134 { return NULL; }
135 static inline block_dev_desc_t* ide_get_dev(int dev) { return NULL; } 135 static inline block_dev_desc_t* ide_get_dev(int dev) { return NULL; }
136 static inline block_dev_desc_t* sata_get_dev(int dev) { return NULL; } 136 static inline block_dev_desc_t* sata_get_dev(int dev) { return NULL; }
137 static inline block_dev_desc_t* scsi_get_dev(int dev) { return NULL; } 137 static inline block_dev_desc_t* scsi_get_dev(int dev) { return NULL; }
138 static inline block_dev_desc_t* usb_stor_get_dev(int dev) { return NULL; } 138 static inline block_dev_desc_t* usb_stor_get_dev(int dev) { return NULL; }
139 static inline block_dev_desc_t* mmc_get_dev(int dev) { return NULL; } 139 static inline block_dev_desc_t* mmc_get_dev(int dev) { return NULL; }
140 static inline block_dev_desc_t* systemace_get_dev(int dev) { return NULL; } 140 static inline block_dev_desc_t* systemace_get_dev(int dev) { return NULL; }
141 static inline block_dev_desc_t* mg_disk_get_dev(int dev) { return NULL; } 141 static inline block_dev_desc_t* mg_disk_get_dev(int dev) { return NULL; }
142 142
143 static inline int get_partition_info (block_dev_desc_t * dev_desc, int part, 143 static inline int get_partition_info (block_dev_desc_t * dev_desc, int part,
144 disk_partition_t *info) { return -1; } 144 disk_partition_t *info) { return -1; }
145 static inline void print_part (block_dev_desc_t *dev_desc) {} 145 static inline void print_part (block_dev_desc_t *dev_desc) {}
146 static inline void init_part (block_dev_desc_t *dev_desc) {} 146 static inline void init_part (block_dev_desc_t *dev_desc) {}
147 static inline void dev_print(block_dev_desc_t *dev_desc) {} 147 static inline void dev_print(block_dev_desc_t *dev_desc) {}
148 static inline int get_device(const char *ifname, const char *dev_str, 148 static inline int get_device(const char *ifname, const char *dev_str,
149 block_dev_desc_t **dev_desc) 149 block_dev_desc_t **dev_desc)
150 { return -1; } 150 { return -1; }
151 static inline int get_device_and_partition(const char *ifname, 151 static inline int get_device_and_partition(const char *ifname,
152 const char *dev_part_str, 152 const char *dev_part_str,
153 block_dev_desc_t **dev_desc, 153 block_dev_desc_t **dev_desc,
154 disk_partition_t *info, 154 disk_partition_t *info,
155 int allow_whole_dev) 155 int allow_whole_dev)
156 { *dev_desc = NULL; return -1; } 156 { *dev_desc = NULL; return -1; }
157 #endif 157 #endif
158 158
159 #ifdef CONFIG_MAC_PARTITION 159 #ifdef CONFIG_MAC_PARTITION
160 /* disk/part_mac.c */ 160 /* disk/part_mac.c */
161 int get_partition_info_mac (block_dev_desc_t * dev_desc, int part, disk_partition_t *info); 161 int get_partition_info_mac (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
162 void print_part_mac (block_dev_desc_t *dev_desc); 162 void print_part_mac (block_dev_desc_t *dev_desc);
163 int test_part_mac (block_dev_desc_t *dev_desc); 163 int test_part_mac (block_dev_desc_t *dev_desc);
164 #endif 164 #endif
165 165
166 #ifdef CONFIG_DOS_PARTITION 166 #ifdef CONFIG_DOS_PARTITION
167 /* disk/part_dos.c */ 167 /* disk/part_dos.c */
168 int get_partition_info_dos (block_dev_desc_t * dev_desc, int part, disk_partition_t *info); 168 int get_partition_info_dos (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
169 void print_part_dos (block_dev_desc_t *dev_desc); 169 void print_part_dos (block_dev_desc_t *dev_desc);
170 int test_part_dos (block_dev_desc_t *dev_desc); 170 int test_part_dos (block_dev_desc_t *dev_desc);
171 #endif 171 #endif
172 172
173 #ifdef CONFIG_ISO_PARTITION 173 #ifdef CONFIG_ISO_PARTITION
174 /* disk/part_iso.c */ 174 /* disk/part_iso.c */
175 int get_partition_info_iso (block_dev_desc_t * dev_desc, int part, disk_partition_t *info); 175 int get_partition_info_iso (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
176 void print_part_iso (block_dev_desc_t *dev_desc); 176 void print_part_iso (block_dev_desc_t *dev_desc);
177 int test_part_iso (block_dev_desc_t *dev_desc); 177 int test_part_iso (block_dev_desc_t *dev_desc);
178 #endif 178 #endif
179 179
180 #ifdef CONFIG_AMIGA_PARTITION 180 #ifdef CONFIG_AMIGA_PARTITION
181 /* disk/part_amiga.c */ 181 /* disk/part_amiga.c */
182 int get_partition_info_amiga (block_dev_desc_t * dev_desc, int part, disk_partition_t *info); 182 int get_partition_info_amiga (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
183 void print_part_amiga (block_dev_desc_t *dev_desc); 183 void print_part_amiga (block_dev_desc_t *dev_desc);
184 int test_part_amiga (block_dev_desc_t *dev_desc); 184 int test_part_amiga (block_dev_desc_t *dev_desc);
185 #endif 185 #endif
186 186
187 #ifdef CONFIG_EFI_PARTITION 187 #ifdef CONFIG_EFI_PARTITION
188 #include <part_efi.h> 188 #include <part_efi.h>
189 /* disk/part_efi.c */ 189 /* disk/part_efi.c */
190 int get_partition_info_efi (block_dev_desc_t * dev_desc, int part, disk_partition_t *info); 190 int get_partition_info_efi (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
191 void print_part_efi (block_dev_desc_t *dev_desc); 191 void print_part_efi (block_dev_desc_t *dev_desc);
192 int test_part_efi (block_dev_desc_t *dev_desc); 192 int test_part_efi (block_dev_desc_t *dev_desc);
193 193
194 /** 194 /**
195 * write_gpt_table() - Write the GUID Partition Table to disk 195 * write_gpt_table() - Write the GUID Partition Table to disk
196 * 196 *
197 * @param dev_desc - block device descriptor 197 * @param dev_desc - block device descriptor
198 * @param gpt_h - pointer to GPT header representation 198 * @param gpt_h - pointer to GPT header representation
199 * @param gpt_e - pointer to GPT partition table entries 199 * @param gpt_e - pointer to GPT partition table entries
200 * 200 *
201 * @return - zero on success, otherwise error 201 * @return - zero on success, otherwise error
202 */ 202 */
203 int write_gpt_table(block_dev_desc_t *dev_desc, 203 int write_gpt_table(block_dev_desc_t *dev_desc,
204 gpt_header *gpt_h, gpt_entry *gpt_e); 204 gpt_header *gpt_h, gpt_entry *gpt_e);
205 205
206 /** 206 /**
207 * gpt_fill_pte(): Fill the GPT partition table entry 207 * gpt_fill_pte(): Fill the GPT partition table entry
208 * 208 *
209 * @param gpt_h - GPT header representation 209 * @param gpt_h - GPT header representation
210 * @param gpt_e - GPT partition table entries 210 * @param gpt_e - GPT partition table entries
211 * @param partitions - list of partitions 211 * @param partitions - list of partitions
212 * @param parts - number of partitions 212 * @param parts - number of partitions
213 * 213 *
214 * @return zero on success 214 * @return zero on success
215 */ 215 */
216 int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, 216 int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
217 disk_partition_t *partitions, int parts); 217 disk_partition_t *partitions, int parts);
218 218
219 /** 219 /**
220 * gpt_fill_header(): Fill the GPT header 220 * gpt_fill_header(): Fill the GPT header
221 * 221 *
222 * @param dev_desc - block device descriptor 222 * @param dev_desc - block device descriptor
223 * @param gpt_h - GPT header representation 223 * @param gpt_h - GPT header representation
224 * @param str_guid - disk guid string representation 224 * @param str_guid - disk guid string representation
225 * @param parts_count - number of partitions 225 * @param parts_count - number of partitions
226 * 226 *
227 * @return - error on str_guid conversion error 227 * @return - error on str_guid conversion error
228 */ 228 */
229 int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h, 229 int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h,
230 char *str_guid, int parts_count); 230 char *str_guid, int parts_count);
231 231
232 /** 232 /**
233 * gpt_restore(): Restore GPT partition table 233 * gpt_restore(): Restore GPT partition table
234 * 234 *
235 * @param dev_desc - block device descriptor 235 * @param dev_desc - block device descriptor
236 * @param str_disk_guid - disk GUID 236 * @param str_disk_guid - disk GUID
237 * @param partitions - list of partitions 237 * @param partitions - list of partitions
238 * @param parts - number of partitions 238 * @param parts - number of partitions
239 * 239 *
240 * @return zero on success 240 * @return zero on success
241 */ 241 */
242 int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid, 242 int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
243 disk_partition_t *partitions, const int parts_count); 243 disk_partition_t *partitions, const int parts_count);
244 #endif 244 #endif
245 245
246 #endif /* _PART_H */ 246 #endif /* _PART_H */
247 247