bigbiff bigbiff | 9c75405 | 2013-01-09 09:09:08 -0500 | [diff] [blame] | 1 | /* |
| 2 | rootdir.c (09.11.10) |
| 3 | Root directory creation code. |
| 4 | |
bigbiff bigbiff | 61cdc02 | 2013-08-08 08:35:06 -0400 | [diff] [blame] | 5 | Free exFAT implementation. |
Matt Mower | 09ef1e4 | 2015-12-13 11:29:45 -0600 | [diff] [blame] | 6 | Copyright (C) 2011-2015 Andrew Nayenko |
bigbiff bigbiff | 9c75405 | 2013-01-09 09:09:08 -0500 | [diff] [blame] | 7 | |
bigbiff bigbiff | 61cdc02 | 2013-08-08 08:35:06 -0400 | [diff] [blame] | 8 | This program is free software; you can redistribute it and/or modify |
bigbiff bigbiff | 9c75405 | 2013-01-09 09:09:08 -0500 | [diff] [blame] | 9 | it under the terms of the GNU General Public License as published by |
bigbiff bigbiff | 61cdc02 | 2013-08-08 08:35:06 -0400 | [diff] [blame] | 10 | the Free Software Foundation, either version 2 of the License, or |
bigbiff bigbiff | 9c75405 | 2013-01-09 09:09:08 -0500 | [diff] [blame] | 11 | (at your option) any later version. |
| 12 | |
| 13 | This program is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. |
| 17 | |
bigbiff bigbiff | 61cdc02 | 2013-08-08 08:35:06 -0400 | [diff] [blame] | 18 | You should have received a copy of the GNU General Public License along |
| 19 | with this program; if not, write to the Free Software Foundation, Inc., |
| 20 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
bigbiff bigbiff | 9c75405 | 2013-01-09 09:09:08 -0500 | [diff] [blame] | 21 | */ |
| 22 | |
bigbiff bigbiff | 9c75405 | 2013-01-09 09:09:08 -0500 | [diff] [blame] | 23 | #include "rootdir.h" |
| 24 | #include "uct.h" |
| 25 | #include "cbm.h" |
| 26 | #include "uctc.h" |
Matt Mower | 09ef1e4 | 2015-12-13 11:29:45 -0600 | [diff] [blame] | 27 | #include <string.h> |
bigbiff bigbiff | 9c75405 | 2013-01-09 09:09:08 -0500 | [diff] [blame] | 28 | |
Spegelius | d69ac2b | 2014-11-23 15:15:06 +0200 | [diff] [blame] | 29 | static loff_t rootdir_alignment(void) |
bigbiff bigbiff | 9c75405 | 2013-01-09 09:09:08 -0500 | [diff] [blame] | 30 | { |
| 31 | return get_cluster_size(); |
| 32 | } |
| 33 | |
Spegelius | d69ac2b | 2014-11-23 15:15:06 +0200 | [diff] [blame] | 34 | static loff_t rootdir_size(void) |
bigbiff bigbiff | 9c75405 | 2013-01-09 09:09:08 -0500 | [diff] [blame] | 35 | { |
| 36 | return get_cluster_size(); |
| 37 | } |
| 38 | |
| 39 | static void init_label_entry(struct exfat_entry_label* label_entry) |
| 40 | { |
| 41 | memset(label_entry, 0, sizeof(struct exfat_entry_label)); |
| 42 | label_entry->type = EXFAT_ENTRY_LABEL ^ EXFAT_ENTRY_VALID; |
| 43 | |
| 44 | if (utf16_length(get_volume_label()) == 0) |
| 45 | return; |
| 46 | |
| 47 | memcpy(label_entry->name, get_volume_label(), |
| 48 | EXFAT_ENAME_MAX * sizeof(le16_t)); |
| 49 | label_entry->length = utf16_length(get_volume_label()); |
| 50 | label_entry->type |= EXFAT_ENTRY_VALID; |
| 51 | } |
| 52 | |
| 53 | static void init_bitmap_entry(struct exfat_entry_bitmap* bitmap_entry) |
| 54 | { |
| 55 | memset(bitmap_entry, 0, sizeof(struct exfat_entry_bitmap)); |
| 56 | bitmap_entry->type = EXFAT_ENTRY_BITMAP; |
| 57 | bitmap_entry->start_cluster = cpu_to_le32(EXFAT_FIRST_DATA_CLUSTER); |
| 58 | bitmap_entry->size = cpu_to_le64(cbm.get_size()); |
| 59 | } |
| 60 | |
| 61 | static void init_upcase_entry(struct exfat_entry_upcase* upcase_entry) |
| 62 | { |
| 63 | size_t i; |
| 64 | uint32_t sum = 0; |
| 65 | |
| 66 | for (i = 0; i < sizeof(upcase_table); i++) |
| 67 | sum = ((sum << 31) | (sum >> 1)) + upcase_table[i]; |
| 68 | |
| 69 | memset(upcase_entry, 0, sizeof(struct exfat_entry_upcase)); |
| 70 | upcase_entry->type = EXFAT_ENTRY_UPCASE; |
| 71 | upcase_entry->checksum = cpu_to_le32(sum); |
| 72 | upcase_entry->start_cluster = cpu_to_le32( |
| 73 | (get_position(&uct) - get_position(&cbm)) / get_cluster_size() + |
| 74 | EXFAT_FIRST_DATA_CLUSTER); |
| 75 | upcase_entry->size = cpu_to_le64(sizeof(upcase_table)); |
| 76 | } |
| 77 | |
| 78 | static int rootdir_write(struct exfat_dev* dev) |
| 79 | { |
| 80 | struct exfat_entry_label label_entry; |
| 81 | struct exfat_entry_bitmap bitmap_entry; |
| 82 | struct exfat_entry_upcase upcase_entry; |
| 83 | |
| 84 | init_label_entry(&label_entry); |
| 85 | init_bitmap_entry(&bitmap_entry); |
| 86 | init_upcase_entry(&upcase_entry); |
| 87 | |
| 88 | if (exfat_write(dev, &label_entry, sizeof(struct exfat_entry)) < 0) |
| 89 | return 1; |
| 90 | if (exfat_write(dev, &bitmap_entry, sizeof(struct exfat_entry)) < 0) |
| 91 | return 1; |
| 92 | if (exfat_write(dev, &upcase_entry, sizeof(struct exfat_entry)) < 0) |
| 93 | return 1; |
| 94 | return 0; |
| 95 | } |
| 96 | |
| 97 | const struct fs_object rootdir = |
| 98 | { |
| 99 | .get_alignment = rootdir_alignment, |
| 100 | .get_size = rootdir_size, |
| 101 | .write = rootdir_write, |
| 102 | }; |