Commit 04735e9c5578dd4f3584be5454b9779e8e5c2af9
Committed by
Tom Rini
1 parent
0eb33ad253
Exists in
master
and in
53 other branches
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
common/cmd_disk.c
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 |
disk/part_efi.c
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 |
disk/part_iso.c
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 |
fs/ext4/dev.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 | * 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 |
fs/ext4/ext4fs.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 | #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 |
include/ext4fs.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 | * 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 |
include/ide.h
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 |
include/part.h
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 |