Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/modules/sd_card_image/image.50.makefs.sh
blob: b259409e2ed5d86911ee25f3573001325f7e55ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Copyright (C) 2009 One Laptop per Child
# Licensed under the terms of the GNU GPL v2 or later; see COPYING for details.

. $OOB__shlib
versioned_fs=$(read_config base versioned_fs)
buildnr=$(read_buildnr)
BLOCK_SIZE=512
ROOT_PARTITION_START_BLOCK=139264
NUM_HEADS=16
NUM_SECTORS_PER_TRACK=62

# FIXME trap signals and cleanup
# FIXME check that traps due to errors are caught
BOOT=$intermediatesdir/mnt-boot
ROOT=$intermediatesdir/mnt-root

umount $BOOT &>/dev/null || :
umount $ROOT &>/dev/null || :
mkdir -p $BOOT
mkdir -p $ROOT

# Automatically determine a size for the output disk image (including root
# and boot partitions).
#
# This is calculated by examining how much space was used in the intermediate
# filesystem image, and by adding a small amount of free space for safety.
auto_size()
{
	local rawfs=$intermediatesdir/rawfs.img
	local edump=$(dumpe2fs "$rawfs")
	local bsize=$(echo "$edump" | grep "^Block size:")
	local bcount=$(echo "$edump" | grep "^Block count:")
	local freeblocks=$(echo "$edump" | grep "^Free blocks:")

	# Remove textual labels, we just want the numbers
	bsize="${bsize##* }"
	bcount="${bcount##* }"
	freeblocks="${freeblocks##* }"

	local usedblocks=$(( bcount - freeblocks ))
	local usedsize=$(( usedblocks * bsize ))

	# In my testing, the new image has about 100mb free even when we try
	# to match the size exactly. So we use the exact size; if we find that
	# we need to add some 'safety' space later, we can add it.
	#local newsize=$(( usedsize + (20*1024*1024) ))
	local newsize=$usedsize

	# Increase by size of boot partition
	(( newsize += $ROOT_PARTITION_START_BLOCK * $BLOCK_SIZE ))

	echo $newsize
}

make_image()
{
	local disk_size=$1
	local ext=$2
	[ -z "$ext" ] && ext="zd"

	if [ "$disk_size" = "auto" ]; then
		disk_size=$(auto_size)
	fi

	echo "Making image of size $disk_size"

	echo "Create disk and partitions..."

	local num_blocks=$(($disk_size / $BLOCK_SIZE))
	local num_cylinders=$(($num_blocks / $NUM_HEADS / $NUM_SECTORS_PER_TRACK))
	local image_size=$(($num_cylinders * $NUM_HEADS * $NUM_SECTORS_PER_TRACK * $BLOCK_SIZE))

	local img=$intermediatesdir/$(image_name).$ext.disk.img

	dd if=/dev/zero of=$img bs=$BLOCK_SIZE count=0 seek=$(($image_size / $BLOCK_SIZE))

	/sbin/sfdisk -S 32 -H 32 --force -uS $img <<EOF
8192,131072,83,*
$ROOT_PARTITION_START_BLOCK,,,
EOF

	disk_loop=$(losetup --show --find --partscan $img)
	boot_loop="${disk_loop}p1"
	root_loop="${disk_loop}p2"

	# Work around occasional failure for loop partitions to appear
	# http://marc.info/?l=linux-kernel&m=134271282127702&w=2
	local i=0
	while ! [ -e "$boot_loop" ]; do
		partx -a -v $disk_loop
		sleep 1
		(( ++i ))
		[ $i -ge 10 ] && break
	done

	echo "Create filesystems..."
	mke2fs -O dir_index,^resize_inode -L Boot -F $boot_loop
	mount $boot_loop $BOOT

	mkfs.ext4 -O dir_index,^huge_file -E resize=8G -m1 -L OLPCRoot $root_loop
	tune2fs -o journal_data_ordered $root_loop
	mount $root_loop $ROOT

	echo "Copy in root filesystem..."
	cp -a $fsmount/* $ROOT

	echo "Setup boot partition..."

	# runin testing needs this directory (#9840)
	# this needs to be done during build so that OFW can put files here
	# (e.g. updated tests) before the OS has ever booted
	mkdir -p $BOOT/runin

	# we put /security here as it's used by OFW, and should persist between
	# updates
	mkdir -p $BOOT/security

	# this is where Fedora's statetab tmpfs mount system puts its data.
	# the directory has to be created in advance
	mkdir -p $BOOT/security/state

	if [ "$versioned_fs" = "1" ]; then
		local tgt=$BOOT/boot-versions/$buildnr
		mkdir -p $tgt
		ln -s boot-versions/$buildnr $BOOT/boot
		ln -s boot/alt $BOOT/boot-alt
		cp -ar $ROOT/versions/pristine/$buildnr/boot/* $tgt
	else
		cp -ar $ROOT/boot/* $BOOT
		ln -s . $BOOT/boot
	fi

	umount $ROOT
	umount $BOOT
	losetup -d $disk_loop || :

	# FIXME: any value to running e2fsck now? maybe with -D ?
}


find_option_values sizes sd_card_image size
for val in "${sizes[@]}"; do
	disk_size=${val%,*}
	ext=
	expr index "$vals" ',' &>/dev/null && ext=${vals#*,}
	make_image $disk_size $ext
done

# If no sizes were specified, create an image with automatic size.
[[ ${#sizes[@]} == 0 ]] && make_image auto