summaryrefslogtreecommitdiffstats
path: root/scripts/lib/wic/utils/partitionedfs.py
diff options
context:
space:
mode:
authorEd Bartosh <ed.bartosh@linux.intel.com>2017-02-09 16:28:54 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-02-15 20:06:44 -0800
commitcdcc6e27530f13531b3bda9a15dc926f6ff9a837 (patch)
treea1993d5b949cde736661ffae78d55ac1b485eaa4 /scripts/lib/wic/utils/partitionedfs.py
parentadf5e2956ca4e3136be0ee785115a7e1941a135b (diff)
downloadpoky-cdcc6e27530f13531b3bda9a15dc926f6ff9a837.tar.gz
wic: move PartitionedImage class to direct.py
As PartitionedImage is only used in direct.py it makes sense to move it there. It's easier to maintain (and refactor) it this way. (From OE-Core rev: 2550622371f5c50857e5d58eabab01a1823c6fc3) Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib/wic/utils/partitionedfs.py')
-rw-r--r--scripts/lib/wic/utils/partitionedfs.py301
1 files changed, 0 insertions, 301 deletions
diff --git a/scripts/lib/wic/utils/partitionedfs.py b/scripts/lib/wic/utils/partitionedfs.py
deleted file mode 100644
index cdf8f08015..0000000000
--- a/scripts/lib/wic/utils/partitionedfs.py
+++ /dev/null
@@ -1,301 +0,0 @@
1#!/usr/bin/env python -tt
2#
3# Copyright (c) 2009, 2010, 2011 Intel, Inc.
4# Copyright (c) 2007, 2008 Red Hat, Inc.
5# Copyright (c) 2008 Daniel P. Berrange
6# Copyright (c) 2008 David P. Huff
7#
8# This program is free software; you can redistribute it and/or modify it
9# under the terms of the GNU General Public License as published by the Free
10# Software Foundation; version 2 of the License
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15# for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program; if not, write to the Free Software Foundation, Inc., 59
19# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
21import os
22
23from wic import msger
24from wic.utils.errors import ImageError
25from wic.utils.misc import exec_native_cmd
26from wic.filemap import sparse_copy
27
28# Overhead of the MBR partitioning scheme (just one sector)
29MBR_OVERHEAD = 1
30
31# Overhead of the GPT partitioning scheme
32GPT_OVERHEAD = 34
33
34# Size of a sector in bytes
35SECTOR_SIZE = 512
36
37class PartitionedImage():
38 """
39 Partitioned image in a file.
40 """
41
42 def __init__(self, path, ptable_format, native_sysroot=None):
43 self.path = path # Path to the image file
44 self.numpart = 0 # Number of allocated partitions
45 self.realpart = 0 # Number of partitions in the partition table
46 self.offset = 0 # Offset of next partition (in sectors)
47 self.min_size = 0 # Minimum required disk size to fit
48 # all partitions (in bytes)
49 self.ptable_format = ptable_format # Partition table format
50 # Disk system identifier
51 self.identifier = int.from_bytes(os.urandom(4), 'little')
52
53 self.partitions = []
54 self.partimages = []
55 # Size of a sector used in calculations
56 self.sector_size = SECTOR_SIZE
57 self.native_sysroot = native_sysroot
58
59 def add_partition(self, part):
60 """
61 Add the next partition. Partitions have to be added in the
62 first-to-last order.
63 """
64 part.ks_pnum = len(self.partitions)
65
66 # Converting kB to sectors for parted
67 part.size_sec = part.disk_size * 1024 // self.sector_size
68
69 self.partitions.append(part)
70
71 def layout_partitions(self):
72 """ Layout the partitions, meaning calculate the position of every
73 partition on the disk. The 'ptable_format' parameter defines the
74 partition table format and may be "msdos". """
75
76 msger.debug("Assigning %s partitions to disks" % self.ptable_format)
77
78 # Go through partitions in the order they are added in .ks file
79 for num in range(len(self.partitions)):
80 part = self.partitions[num]
81
82 if self.ptable_format == 'msdos' and part.part_type:
83 # The --part-type can also be implemented for MBR partitions,
84 # in which case it would map to the 1-byte "partition type"
85 # filed at offset 3 of the partition entry.
86 raise ImageError("setting custom partition type is not " \
87 "implemented for msdos partitions")
88
89 # Get the disk where the partition is located
90 self.numpart += 1
91 if not part.no_table:
92 self.realpart += 1
93
94 if self.numpart == 1:
95 if self.ptable_format == "msdos":
96 overhead = MBR_OVERHEAD
97 elif self.ptable_format == "gpt":
98 overhead = GPT_OVERHEAD
99
100 # Skip one sector required for the partitioning scheme overhead
101 self.offset += overhead
102
103 if self.realpart > 3:
104 # Reserve a sector for EBR for every logical partition
105 # before alignment is performed.
106 if self.ptable_format == "msdos":
107 self.offset += 1
108
109 if part.align:
110 # If not first partition and we do have alignment set we need
111 # to align the partition.
112 # FIXME: This leaves a empty spaces to the disk. To fill the
113 # gaps we could enlargea the previous partition?
114
115 # Calc how much the alignment is off.
116 align_sectors = self.offset % (part.align * 1024 // self.sector_size)
117
118 if align_sectors:
119 # If partition is not aligned as required, we need
120 # to move forward to the next alignment point
121 align_sectors = (part.align * 1024 // self.sector_size) - align_sectors
122
123 msger.debug("Realignment for %s%s with %s sectors, original"
124 " offset %s, target alignment is %sK." %
125 (part.disk, self.numpart, align_sectors,
126 self.offset, part.align))
127
128 # increase the offset so we actually start the partition on right alignment
129 self.offset += align_sectors
130
131 part.start = self.offset
132 self.offset += part.size_sec
133
134 part.type = 'primary'
135 if not part.no_table:
136 part.num = self.realpart
137 else:
138 part.num = 0
139
140 if self.ptable_format == "msdos":
141 # only count the partitions that are in partition table
142 if len([p for p in self.partitions if not p.no_table]) > 4:
143 if self.realpart > 3:
144 part.type = 'logical'
145 part.num = self.realpart + 1
146
147 msger.debug("Assigned %s to %s%d, sectors range %d-%d size %d "
148 "sectors (%d bytes)." \
149 % (part.mountpoint, part.disk, part.num,
150 part.start, self.offset - 1,
151 part.size_sec, part.size_sec * self.sector_size))
152
153 # Once all the partitions have been layed out, we can calculate the
154 # minumim disk size
155 self.min_size = self.offset
156 if self.ptable_format == "gpt":
157 self.min_size += GPT_OVERHEAD
158
159 self.min_size *= self.sector_size
160
161 def _create_partition(self, device, parttype, fstype, start, size):
162 """ Create a partition on an image described by the 'device' object. """
163
164 # Start is included to the size so we need to substract one from the end.
165 end = start + size - 1
166 msger.debug("Added '%s' partition, sectors %d-%d, size %d sectors" %
167 (parttype, start, end, size))
168
169 cmd = "parted -s %s unit s mkpart %s" % (device, parttype)
170 if fstype:
171 cmd += " %s" % fstype
172 cmd += " %d %d" % (start, end)
173
174 return exec_native_cmd(cmd, self.native_sysroot)
175
176 def create(self):
177 msger.debug("Creating sparse file %s" % self.path)
178 with open(self.path, 'w') as sparse:
179 os.ftruncate(sparse.fileno(), self.min_size)
180
181 msger.debug("Initializing partition table for %s" % self.path)
182 exec_native_cmd("parted -s %s mklabel %s" %
183 (self.path, self.ptable_format), self.native_sysroot)
184
185 msger.debug("Set disk identifier %x" % self.identifier)
186 with open(self.path, 'r+b') as img:
187 img.seek(0x1B8)
188 img.write(self.identifier.to_bytes(4, 'little'))
189
190 msger.debug("Creating partitions")
191
192 for part in self.partitions:
193 if part.num == 0:
194 continue
195
196 if self.ptable_format == "msdos" and part.num == 5:
197 # Create an extended partition (note: extended
198 # partition is described in MBR and contains all
199 # logical partitions). The logical partitions save a
200 # sector for an EBR just before the start of a
201 # partition. The extended partition must start one
202 # sector before the start of the first logical
203 # partition. This way the first EBR is inside of the
204 # extended partition. Since the extended partitions
205 # starts a sector before the first logical partition,
206 # add a sector at the back, so that there is enough
207 # room for all logical partitions.
208 self._create_partition(self.path, "extended",
209 None, part.start - 1,
210 self.offset - part.start + 1)
211
212 if part.fstype == "swap":
213 parted_fs_type = "linux-swap"
214 elif part.fstype == "vfat":
215 parted_fs_type = "fat32"
216 elif part.fstype == "msdos":
217 parted_fs_type = "fat16"
218 elif part.fstype == "ontrackdm6aux3":
219 parted_fs_type = "ontrackdm6aux3"
220 else:
221 # Type for ext2/ext3/ext4/btrfs
222 parted_fs_type = "ext2"
223
224 # Boot ROM of OMAP boards require vfat boot partition to have an
225 # even number of sectors.
226 if part.mountpoint == "/boot" and part.fstype in ["vfat", "msdos"] \
227 and part.size_sec % 2:
228 msger.debug("Subtracting one sector from '%s' partition to " \
229 "get even number of sectors for the partition" % \
230 part.mountpoint)
231 part.size_sec -= 1
232
233 self._create_partition(self.path, part.type,
234 parted_fs_type, part.start, part.size_sec)
235
236 if part.part_type:
237 msger.debug("partition %d: set type UID to %s" % \
238 (part.num, part.part_type))
239 exec_native_cmd("sgdisk --typecode=%d:%s %s" % \
240 (part.num, part.part_type,
241 self.path), self.native_sysroot)
242
243 if part.uuid and self.ptable_format == "gpt":
244 msger.debug("partition %d: set UUID to %s" % \
245 (part.num, part.uuid))
246 exec_native_cmd("sgdisk --partition-guid=%d:%s %s" % \
247 (part.num, part.uuid, self.path),
248 self.native_sysroot)
249
250 if part.label and self.ptable_format == "gpt":
251 msger.debug("partition %d: set name to %s" % \
252 (part.num, part.label))
253 exec_native_cmd("parted -s %s name %d %s" % \
254 (self.path, part.num, part.label),
255 self.native_sysroot)
256
257 if part.active:
258 flag_name = "legacy_boot" if self.ptable_format == 'gpt' else "boot"
259 msger.debug("Set '%s' flag for partition '%s' on disk '%s'" % \
260 (flag_name, part.num, self.path))
261 exec_native_cmd("parted -s %s set %d %s on" % \
262 (self.path, part.num, flag_name),
263 self.native_sysroot)
264 if part.system_id:
265 exec_native_cmd("sfdisk --part-type %s %s %s" % \
266 (self.path, part.num, part.system_id),
267 self.native_sysroot)
268
269 # Parted defaults to enabling the lba flag for fat16 partitions,
270 # which causes compatibility issues with some firmware (and really
271 # isn't necessary).
272 if parted_fs_type == "fat16":
273 if self.ptable_format == 'msdos':
274 msger.debug("Disable 'lba' flag for partition '%s' on disk '%s'" % \
275 (part.num, self.path))
276 exec_native_cmd("parted -s %s set %d lba off" % \
277 (self.path, part.num),
278 self.native_sysroot)
279
280 def cleanup(self):
281 # remove partition images
282 for image in self.partimages:
283 os.remove(image)
284
285 def assemble(self):
286 msger.debug("Installing partitions")
287
288 for part in self.partitions:
289 source = part.source_file
290 if source:
291 # install source_file contents into a partition
292 sparse_copy(source, self.path, part.start * self.sector_size)
293
294 msger.debug("Installed %s in partition %d, sectors %d-%d, "
295 "size %d sectors" % \
296 (source, part.num, part.start,
297 part.start + part.size_sec - 1, part.size_sec))
298
299 partimage = self.path + '.p%d' % part.num
300 os.rename(source, partimage)
301 self.partimages.append(partimage)