fs.c revision 0cb61411eadd92b7202e045c1c9ec8df7fb636fe
1f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle/*
2f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * Copyright (C) 2010 The Android Open Source Project
3f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle *
4f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * Licensed under the Apache License, Version 2.0 (the "License");
5f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * you may not use this file except in compliance with the License.
6f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * You may obtain a copy of the License at
7f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle *
8f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle *      http://www.apache.org/licenses/LICENSE-2.0
9f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle *
10f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * Unless required by applicable law or agreed to in writing, software
11f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * distributed under the License is distributed on an "AS IS" BASIS,
12f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * See the License for the specific language governing permissions and
14f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * limitations under the License.
15f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle */
16f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
17f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <assert.h>
18f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <string.h>
19f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <sys/endian.h>
20f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
210cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle#include "fatblock.h"
22f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fat.h"
23f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fs.h"
24f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "utils.h"
25f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
26f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#define DEFAULT_SECTOR_SIZE 512
27f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
28f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void fs_add_extent(struct fs *fs, struct extent *extent,
29f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                          offset_t start, offset_t len, int type)
30f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
31f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(fs);
32f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(extent);
33f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
34f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	extent->start = start;
35f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	extent->len = len;
36f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	extent->type = type;
37f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
38f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	extent->next = fs->extents;
39f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->extents = extent;
40f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
41f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
42f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestruct extent *fs_find_extent(struct fs *fs, offset_t start, offset_t len,
43f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                              struct extent *last,
44f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                              offset_t *r_start_out,
45f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                              offset_t *e_start_out,
46f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                              offset_t *len_out)
47f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
48f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct extent *e;
49f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	offset_t end;
50f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	offset_t e_start, e_end, e_len, e_rel_start, r_rel_start, rel_len;
51f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
52f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(fs);
53f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
54f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	end = start + len;
55f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
56f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	e = last ? last->next : fs->extents;
57f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (; e; e = e->next) {
58f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		e_start = e->start;
59f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		e_len = e->len;
60f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		e_end = e_start + e_len;
61f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
62f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (start >= e_end)
63f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			continue;
64f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
65f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (end <= e_start)
66f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			continue;
67f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
68f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (e_start <= start) {
69f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			r_rel_start = 0;
70f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			e_rel_start = start - e_start;
71f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			if (end <= e_end)
72f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				rel_len = len;
73f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			else
74f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				rel_len = e_end - start;
75f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		} else {
76f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			e_rel_start = 0;
77f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			r_rel_start = e_start - start;
78f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			if (e_end <= end)
79f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				rel_len = e_len;
80f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			else
81f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				rel_len = end - e_start;
82f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
83f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
84f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		assert(e_rel_start < e_len);
85f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		assert(e_rel_start + rel_len <= e_len);
86f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		assert(r_rel_start < len);
87f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		assert(r_rel_start + rel_len <= len);
88f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
89f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (r_start_out)
90f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			*r_start_out = r_rel_start;
91f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (e_start_out)
92f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			*e_start_out = e_rel_start;
93f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (len_out)
94f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			*len_out = rel_len;
95f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
96f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return e;
97f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
98f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
99f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return NULL;
100f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
101f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
102f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void fs_set_fat(struct fs *fs, cluster_t cluster, fat_entry_t entry)
103f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
104f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(fs);
105f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
106f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->fat[cluster] = htole32(entry);
107f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
108f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
109f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttleint fs_alloc_extent(struct fs *fs, struct extent *extent,
110f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                    offset_t len, int type, cluster_t *first_cluster_out)
111f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
112f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(fs);
113f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(extent);
114f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
115f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	cluster_t clusters_needed, start;
116f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	cluster_t i;
117f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
118f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (len == 0) {
119f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		extent->start = 0;
120f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		extent->len = 0;
121f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		extent->type = type;
122f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		*first_cluster_out = 0;
123f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return 0;
124f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
125f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
126f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	clusters_needed = (len + fs->cluster_size - 1) / fs->cluster_size;
127f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
128f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	/* Check for adequate space. */
129f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (fs->next_cluster + clusters_needed > fs->num_clusters) {
130f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("allocating extent: filesystem is full!\n");
131f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return -1;
132f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
133f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
134f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	/* Allocate clusters. */
135f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	start = fs->next_cluster;
136f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->next_cluster += clusters_needed;
137f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
138f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	/* Update FAT. */
139f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (i = 0; i < clusters_needed - 1; i++) {
140f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		fs_set_fat(fs, start + i, start + i + 1);
141f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
142f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_set_fat(fs, start + clusters_needed - 1, FAT_ENTRY_EOC);
143f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
144f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	*first_cluster_out = start;
145f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
146f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_add_extent(fs,
147f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      extent,
148f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      fs->data_offset + (offset_t)(start - FAT_CLUSTER_ZERO)
149f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                                        * fs->cluster_size,
150f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      (offset_t)clusters_needed * fs->cluster_size,
151f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      type);
152f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
153f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
154f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
155f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
1560cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttleint fs_init(struct fs *fs, uint16_t cluster_size, offset_t data_size,
1570cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle	    offset_t *total_size_out)
158f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
159f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	uint16_t sector_size;
160f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	cluster_t data_clusters;
161f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	sector_t reserved_sectors, fat_sectors, data_sectors, total_sectors;
162f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	sector_t sectors_per_cluster;
163f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int fat_entries_per_sector;
164f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fat_entry_t *fat;
165f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct fat_boot_sector *bs;
166f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct fat_info_sector *is;
167f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
168f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(fs);
169f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
170f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	sector_size = DEFAULT_SECTOR_SIZE;
171f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->cluster_size = cluster_size;
172f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
173f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	sectors_per_cluster = cluster_size / DEFAULT_SECTOR_SIZE;
174f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fat_entries_per_sector = sector_size / sizeof(fat_entry_t);
175f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
176f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	data_clusters = (data_size + cluster_size - 1) / cluster_size;
177f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	data_sectors = data_clusters * sectors_per_cluster;
178f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fat_sectors = ((data_clusters + 2) + fat_entries_per_sector - 1)
179f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      / fat_entries_per_sector;
180f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	reserved_sectors = 3;
181f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	total_sectors = reserved_sectors + fat_sectors + data_sectors;
182f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
183f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memset(&fs->boot, 0, sizeof(fs->boot));
184f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs = &fs->boot;
185f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
186f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	strpadcpy(bs->name, "FATBLOCK", ' ', sizeof(bs->name));
187f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->sector_size = htole16(sector_size);
188f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->sectors_per_cluster = sectors_per_cluster;
189f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->reserved_sectors = htole16(reserved_sectors);
190f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->fats = 1;
191f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->media_desc = FAT_MEDIA_DESC_FIXED;
192f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	/* TODO: Calculate geometry? */
193f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->sectors_per_track = htole16(42);
194f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->heads = htole16(42);
195f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->sectors32 = htole32(total_sectors);
196f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->fat_sectors32 = htole32(fat_sectors);
197f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	/* bs->rootdir_start will be set later. */
198f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->fs_info_sector = htole16(1);
199f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->backup_boot_sector = htole16(2);
200f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->phys_drive = FAT_PHYS_DRIVE_REMOVABLE;
201f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->ext_boot_sig = FAT_EXT_BOOT_SIG;
202f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	bs->serial = 0x42424242;
203f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	strpadcpy(bs->vol_label, "FATBLOCK", ' ', sizeof(bs->vol_label));
204f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	strpadcpy(bs->type, "FAT32", ' ', sizeof(bs->type));
205f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memcpy(bs->boot_sig, FAT_BOOT_SIG, sizeof(bs->boot_sig));
206f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
207f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memset(&fs->info, 0, sizeof(fs->info));
208f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	is = &fs->info;
209f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
210f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memcpy(is->info_sig1, FAT_INFO_SIG1, sizeof(is->info_sig1));
211f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memcpy(is->info_sig2, FAT_INFO_SIG2, sizeof(is->info_sig2));
212f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	is->free_clusters = htole32(-1);
213f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	is->last_cluster = htole32(FAT_CLUSTER_ZERO);
214f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memcpy(is->info_sig3, FAT_INFO_SIG3, sizeof(is->info_sig3));
215f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
216f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->num_clusters = FAT_CLUSTER_ZERO + data_clusters;
217f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->next_cluster = FAT_CLUSTER_ZERO;
218f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
219f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->fat_size = fat_sectors * sector_size;
220f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->fat = malloc(fs->fat_size);
221f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!fs->fat) {
2220cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("initializing filesystem: couldn't allocate FAT extent: "
2230cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     "out of memory\n");
224f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return MALLOC_FAIL;
225f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
226f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memset(fs->fat, 0, fs->fat_size);
227f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
228f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->data_offset = (reserved_sectors + fat_sectors) * sector_size;
229f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
230f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->extents = NULL;
231f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_add_extent(fs, &fs->boot_extent,
232f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      0, sector_size,
233f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      EXTENT_TYPE_BOOT);
234f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_add_extent(fs, &fs->info_extent,
235f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      sector_size, sector_size,
236f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      EXTENT_TYPE_INFO);
237f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_add_extent(fs, &fs->backup_boot_extent,
238f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      2 * sector_size, sector_size,
239f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      EXTENT_TYPE_BOOT);
240f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_add_extent(fs, &fs->fat_extent,
241f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      reserved_sectors * sector_size, fs->fat_size,
242f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                      EXTENT_TYPE_FAT);
243f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
244f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	*total_size_out = (offset_t)total_sectors * sector_size;
245f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
246f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
247f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
248f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
249f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlevoid fs_set_rootdir_start(struct fs *fs, cluster_t rootdir_start)
250f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
251f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(fs);
252f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
253f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->boot.rootdir_start = htole32(rootdir_start);
254f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
255f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
256f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlevoid fs_update_free_clusters(struct fs *fs)
257f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
258f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(fs);
259f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
260f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs->info.free_clusters = htole32(fs->num_clusters - fs->next_cluster);
261f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
262