mirror of
https://git.yoctoproject.org/poky
synced 2026-06-11 16:30:23 +00:00
wic: Rename /mic to /wic
As well as any other stray instances of mic in the codebase that can be removed. We don't really need to carry around legacy naming, and the history is in git. (From OE-Core rev: 598b120406dc1d2b7e377bd1ab6f0acbef034b22) Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
committed by
Richard Purdie
parent
a43c1f9420
commit
d8f9d05bae
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/python -tt
|
||||
#
|
||||
# Copyright (c) 2007 Red Hat, Inc.
|
||||
# Copyright (c) 2011 Intel, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; version 2 of the License
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
class CreatorError(Exception):
|
||||
"""An exception base class for all imgcreate errors."""
|
||||
keyword = '<creator>'
|
||||
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
|
||||
def __str__(self):
|
||||
if isinstance(self.msg, unicode):
|
||||
self.msg = self.msg.encode('utf-8', 'ignore')
|
||||
else:
|
||||
self.msg = str(self.msg)
|
||||
return self.keyword + self.msg
|
||||
|
||||
class Usage(CreatorError):
|
||||
keyword = '<usage>'
|
||||
|
||||
def __str__(self):
|
||||
if isinstance(self.msg, unicode):
|
||||
self.msg = self.msg.encode('utf-8', 'ignore')
|
||||
else:
|
||||
self.msg = str(self.msg)
|
||||
return self.keyword + self.msg + ', please use "--help" for more info'
|
||||
|
||||
class KsError(CreatorError):
|
||||
keyword = '<kickstart>'
|
||||
|
||||
class ImageError(CreatorError):
|
||||
keyword = '<mount>'
|
||||
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/python -tt
|
||||
#
|
||||
# Copyright (c) 2007, Red Hat, Inc.
|
||||
# Copyright (c) 2009, 2010, 2011 Intel, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; version 2 of the License
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
import sys
|
||||
import errno
|
||||
import stat
|
||||
import random
|
||||
import string
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from wic import msger
|
||||
from wic.utils import runner
|
||||
from wic.utils.errors import *
|
||||
from wic.utils.oe.misc import *
|
||||
|
||||
def find_binary_path(binary):
|
||||
if os.environ.has_key("PATH"):
|
||||
paths = os.environ["PATH"].split(":")
|
||||
else:
|
||||
paths = []
|
||||
if os.environ.has_key("HOME"):
|
||||
paths += [os.environ["HOME"] + "/bin"]
|
||||
paths += ["/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "/bin"]
|
||||
|
||||
for path in paths:
|
||||
bin_path = "%s/%s" % (path, binary)
|
||||
if os.path.exists(bin_path):
|
||||
return bin_path
|
||||
|
||||
print "External command '%s' not found, exiting." % binary
|
||||
print " (Please install '%s' on your host system)" % binary
|
||||
sys.exit(1)
|
||||
|
||||
def makedirs(dirname):
|
||||
"""A version of os.makedirs() that doesn't throw an
|
||||
exception if the leaf directory already exists.
|
||||
"""
|
||||
try:
|
||||
os.makedirs(dirname)
|
||||
except OSError, err:
|
||||
if err.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
class Disk:
|
||||
"""
|
||||
Generic base object for a disk.
|
||||
"""
|
||||
def __init__(self, size, device = None):
|
||||
self._device = device
|
||||
self._size = size
|
||||
|
||||
def create(self):
|
||||
pass
|
||||
|
||||
def cleanup(self):
|
||||
pass
|
||||
|
||||
def get_device(self):
|
||||
return self._device
|
||||
def set_device(self, path):
|
||||
self._device = path
|
||||
device = property(get_device, set_device)
|
||||
|
||||
def get_size(self):
|
||||
return self._size
|
||||
size = property(get_size)
|
||||
|
||||
|
||||
class DiskImage(Disk):
|
||||
"""
|
||||
A Disk backed by a file.
|
||||
"""
|
||||
def __init__(self, image_file, size):
|
||||
Disk.__init__(self, size)
|
||||
self.image_file = image_file
|
||||
|
||||
def exists(self):
|
||||
return os.path.exists(self.image_file)
|
||||
|
||||
def create(self):
|
||||
if self.device is not None:
|
||||
return
|
||||
|
||||
blocks = self.size / 1024
|
||||
if self.size - blocks * 1024:
|
||||
blocks += 1
|
||||
|
||||
# create disk image
|
||||
dd_cmd = "dd if=/dev/zero of=%s bs=1024 seek=%d count=1" % \
|
||||
(self.image_file, blocks)
|
||||
exec_cmd(dd_cmd)
|
||||
|
||||
self.device = self.image_file
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/python -tt
|
||||
#
|
||||
# Copyright (c) 2010, 2011 Intel Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; version 2 of the License
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
def build_name(kscfg, release=None, prefix = None, suffix = None):
|
||||
"""Construct and return an image name string.
|
||||
|
||||
This is a utility function to help create sensible name and fslabel
|
||||
strings. The name is constructed using the sans-prefix-and-extension
|
||||
kickstart filename and the supplied prefix and suffix.
|
||||
|
||||
kscfg -- a path to a kickstart file
|
||||
release -- a replacement to suffix for image release
|
||||
prefix -- a prefix to prepend to the name; defaults to None, which causes
|
||||
no prefix to be used
|
||||
suffix -- a suffix to append to the name; defaults to None, which causes
|
||||
a YYYYMMDDHHMM suffix to be used
|
||||
|
||||
Note, if maxlen is less then the len(suffix), you get to keep both pieces.
|
||||
|
||||
"""
|
||||
name = os.path.basename(kscfg)
|
||||
idx = name.rfind('.')
|
||||
if idx >= 0:
|
||||
name = name[:idx]
|
||||
|
||||
if release is not None:
|
||||
suffix = ""
|
||||
if prefix is None:
|
||||
prefix = ""
|
||||
if suffix is None:
|
||||
suffix = time.strftime("%Y%m%d%H%M")
|
||||
|
||||
if name.startswith(prefix):
|
||||
name = name[len(prefix):]
|
||||
|
||||
prefix = "%s-" % prefix if prefix else ""
|
||||
suffix = "-%s" % suffix if suffix else ""
|
||||
|
||||
ret = prefix + name + suffix
|
||||
|
||||
return ret
|
||||
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# OpenEmbedded wic utils library
|
||||
#
|
||||
# Copyright (c) 2013, Intel Corporation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# AUTHORS
|
||||
# Tom Zanussi <tom.zanussi (at] linux.intel.com>
|
||||
#
|
||||
@@ -0,0 +1,181 @@
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# Copyright (c) 2013, Intel Corporation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# DESCRIPTION
|
||||
# This module provides a place to collect various wic-related utils
|
||||
# for the OpenEmbedded Image Tools.
|
||||
#
|
||||
# AUTHORS
|
||||
# Tom Zanussi <tom.zanussi (at] linux.intel.com>
|
||||
#
|
||||
|
||||
from wic import msger
|
||||
from wic.utils import runner
|
||||
|
||||
def __exec_cmd(cmd_and_args, as_shell = False, catch = 3):
|
||||
"""
|
||||
Execute command, catching stderr, stdout
|
||||
|
||||
Need to execute as_shell if the command uses wildcards
|
||||
"""
|
||||
msger.debug("__exec_cmd: %s" % cmd_and_args)
|
||||
args = cmd_and_args.split()
|
||||
msger.debug(args)
|
||||
|
||||
if (as_shell):
|
||||
rc, out = runner.runtool(cmd_and_args, catch)
|
||||
else:
|
||||
rc, out = runner.runtool(args, catch)
|
||||
out = out.strip()
|
||||
msger.debug("__exec_cmd: output for %s (rc = %d): %s" % \
|
||||
(cmd_and_args, rc, out))
|
||||
|
||||
return (rc, out)
|
||||
|
||||
|
||||
def exec_cmd(cmd_and_args, as_shell = False, catch = 3):
|
||||
"""
|
||||
Execute command, catching stderr, stdout
|
||||
|
||||
Exits if rc non-zero
|
||||
"""
|
||||
rc, out = __exec_cmd(cmd_and_args, as_shell, catch)
|
||||
|
||||
if rc != 0:
|
||||
msger.error("exec_cmd: %s returned '%s' instead of 0" % (cmd_and_args, rc))
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def exec_cmd_quiet(cmd_and_args, as_shell = False):
|
||||
"""
|
||||
Execute command, catching nothing in the output
|
||||
|
||||
Exits if rc non-zero
|
||||
"""
|
||||
return exec_cmd(cmd_and_args, as_shell, 0)
|
||||
|
||||
|
||||
def exec_native_cmd(cmd_and_args, native_sysroot, catch = 3):
|
||||
"""
|
||||
Execute native command, catching stderr, stdout
|
||||
|
||||
Need to execute as_shell if the command uses wildcards
|
||||
|
||||
Always need to execute native commands as_shell
|
||||
"""
|
||||
native_paths = \
|
||||
"export PATH=%s/sbin:%s/usr/sbin:%s/usr/bin:$PATH" % \
|
||||
(native_sysroot, native_sysroot, native_sysroot)
|
||||
native_cmd_and_args = "%s;%s" % (native_paths, cmd_and_args)
|
||||
msger.debug("exec_native_cmd: %s" % cmd_and_args)
|
||||
|
||||
args = cmd_and_args.split()
|
||||
msger.debug(args)
|
||||
|
||||
rc, out = __exec_cmd(native_cmd_and_args, True, catch)
|
||||
|
||||
if rc == 127: # shell command-not-found
|
||||
msger.error("A native (host) program required to build the image "
|
||||
"was not found (see details above). Please make sure "
|
||||
"it's installed and try again.")
|
||||
|
||||
return (rc, out)
|
||||
|
||||
|
||||
def exec_native_cmd_quiet(cmd_and_args, native_sysroot):
|
||||
"""
|
||||
Execute native command, catching nothing in the output
|
||||
|
||||
Need to execute as_shell if the command uses wildcards
|
||||
|
||||
Always need to execute native commands as_shell
|
||||
"""
|
||||
return exec_native_cmd(cmd_and_args, native_sysroot, 0)
|
||||
|
||||
|
||||
# kickstart doesn't support variable substution in commands, so this
|
||||
# is our current simplistic scheme for supporting that
|
||||
|
||||
wks_vars = dict()
|
||||
|
||||
def get_wks_var(key):
|
||||
return wks_vars[key]
|
||||
|
||||
def add_wks_var(key, val):
|
||||
wks_vars[key] = val
|
||||
|
||||
BOOTDD_EXTRA_SPACE = 16384
|
||||
IMAGE_EXTRA_SPACE = 10240
|
||||
|
||||
__bitbake_env_lines = ""
|
||||
|
||||
def set_bitbake_env_lines(bitbake_env_lines):
|
||||
global __bitbake_env_lines
|
||||
__bitbake_env_lines = bitbake_env_lines
|
||||
|
||||
def get_bitbake_env_lines():
|
||||
return __bitbake_env_lines
|
||||
|
||||
def find_bitbake_env_lines(image_name):
|
||||
"""
|
||||
If image_name is empty, plugins might still be able to use the
|
||||
environment, so set it regardless.
|
||||
"""
|
||||
if image_name:
|
||||
bitbake_env_cmd = "bitbake -e %s" % image_name
|
||||
else:
|
||||
bitbake_env_cmd = "bitbake -e"
|
||||
rc, bitbake_env_lines = __exec_cmd(bitbake_env_cmd)
|
||||
if rc != 0:
|
||||
print "Couldn't get '%s' output." % bitbake_env_cmd
|
||||
return None
|
||||
|
||||
return bitbake_env_lines
|
||||
|
||||
def find_artifact(bitbake_env_lines, variable):
|
||||
"""
|
||||
Gather the build artifact for the current image (the image_name
|
||||
e.g. core-image-minimal) for the current MACHINE set in local.conf
|
||||
"""
|
||||
retval = ""
|
||||
|
||||
for line in bitbake_env_lines.split('\n'):
|
||||
if (get_line_val(line, variable)):
|
||||
retval = get_line_val(line, variable)
|
||||
break
|
||||
|
||||
return retval
|
||||
|
||||
def get_line_val(line, key):
|
||||
"""
|
||||
Extract the value from the VAR="val" string
|
||||
"""
|
||||
if line.startswith(key + "="):
|
||||
stripped_line = line.split('=')[1]
|
||||
stripped_line = stripped_line.replace('\"', '')
|
||||
return stripped_line
|
||||
return None
|
||||
|
||||
def get_bitbake_var(key):
|
||||
for line in __bitbake_env_lines.split('\n'):
|
||||
if (get_line_val(line, key)):
|
||||
val = get_line_val(line, key)
|
||||
return val
|
||||
return None
|
||||
@@ -0,0 +1,360 @@
|
||||
#!/usr/bin/python -tt
|
||||
#
|
||||
# Copyright (c) 2009, 2010, 2011 Intel, Inc.
|
||||
# Copyright (c) 2007, 2008 Red Hat, Inc.
|
||||
# Copyright (c) 2008 Daniel P. Berrange
|
||||
# Copyright (c) 2008 David P. Huff
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; version 2 of the License
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
import os
|
||||
|
||||
from wic import msger
|
||||
from wic.utils import runner
|
||||
from wic.utils.errors import ImageError
|
||||
from wic.utils.fs_related import *
|
||||
from wic.utils.oe.misc import *
|
||||
|
||||
# Overhead of the MBR partitioning scheme (just one sector)
|
||||
MBR_OVERHEAD = 1
|
||||
|
||||
# Size of a sector in bytes
|
||||
SECTOR_SIZE = 512
|
||||
|
||||
class Image:
|
||||
"""
|
||||
Generic base object for an image.
|
||||
|
||||
An Image is a container for a set of DiskImages and associated
|
||||
partitions.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.disks = {}
|
||||
self.partitions = []
|
||||
self.parted = find_binary_path("parted")
|
||||
# Size of a sector used in calculations
|
||||
self.sector_size = SECTOR_SIZE
|
||||
self._partitions_layed_out = False
|
||||
|
||||
def __add_disk(self, disk_name):
|
||||
""" Add a disk 'disk_name' to the internal list of disks. Note,
|
||||
'disk_name' is the name of the disk in the target system
|
||||
(e.g., sdb). """
|
||||
|
||||
if disk_name in self.disks:
|
||||
# We already have this disk
|
||||
return
|
||||
|
||||
assert not self._partitions_layed_out
|
||||
|
||||
self.disks[disk_name] = \
|
||||
{ 'disk': None, # Disk object
|
||||
'numpart': 0, # Number of allocate partitions
|
||||
'partitions': [], # Indexes to self.partitions
|
||||
'offset': 0, # Offset of next partition (in sectors)
|
||||
# Minimum required disk size to fit all partitions (in bytes)
|
||||
'min_size': 0,
|
||||
'ptable_format': "msdos" } # Partition table format
|
||||
|
||||
def add_disk(self, disk_name, disk_obj):
|
||||
""" Add a disk object which have to be partitioned. More than one disk
|
||||
can be added. In case of multiple disks, disk partitions have to be
|
||||
added for each disk separately with 'add_partition()". """
|
||||
|
||||
self.__add_disk(disk_name)
|
||||
self.disks[disk_name]['disk'] = disk_obj
|
||||
|
||||
def __add_partition(self, part):
|
||||
""" This is a helper function for 'add_partition()' which adds a
|
||||
partition to the internal list of partitions. """
|
||||
|
||||
assert not self._partitions_layed_out
|
||||
|
||||
self.partitions.append(part)
|
||||
self.__add_disk(part['disk_name'])
|
||||
|
||||
def add_partition(self, size, disk_name, mountpoint, source_file = None, fstype = None,
|
||||
label=None, fsopts = None, boot = False, align = None,
|
||||
part_type = None):
|
||||
""" Add the next partition. Prtitions have to be added in the
|
||||
first-to-last order. """
|
||||
|
||||
ks_pnum = len(self.partitions)
|
||||
|
||||
# Converting MB to sectors for parted
|
||||
size = size * 1024 * 1024 / self.sector_size
|
||||
|
||||
# We still need partition for "/" or non-subvolume
|
||||
if mountpoint == "/" or not fsopts:
|
||||
part = { 'ks_pnum' : ks_pnum, # Partition number in the KS file
|
||||
'size': size, # In sectors
|
||||
'mountpoint': mountpoint, # Mount relative to chroot
|
||||
'source_file': source_file, # partition contents
|
||||
'fstype': fstype, # Filesystem type
|
||||
'fsopts': fsopts, # Filesystem mount options
|
||||
'label': label, # Partition label
|
||||
'disk_name': disk_name, # physical disk name holding partition
|
||||
'device': None, # kpartx device node for partition
|
||||
'num': None, # Partition number
|
||||
'boot': boot, # Bootable flag
|
||||
'align': align, # Partition alignment
|
||||
'part_type' : part_type } # Partition type
|
||||
|
||||
self.__add_partition(part)
|
||||
|
||||
def layout_partitions(self, ptable_format = "msdos"):
|
||||
""" Layout the partitions, meaning calculate the position of every
|
||||
partition on the disk. The 'ptable_format' parameter defines the
|
||||
partition table format and may be "msdos". """
|
||||
|
||||
msger.debug("Assigning %s partitions to disks" % ptable_format)
|
||||
|
||||
if ptable_format not in ('msdos'):
|
||||
raise ImageError("Unknown partition table format '%s', supported " \
|
||||
"formats are: 'msdos'" % ptable_format)
|
||||
|
||||
if self._partitions_layed_out:
|
||||
return
|
||||
|
||||
self._partitions_layed_out = True
|
||||
|
||||
# Go through partitions in the order they are added in .ks file
|
||||
for n in range(len(self.partitions)):
|
||||
p = self.partitions[n]
|
||||
|
||||
if not self.disks.has_key(p['disk_name']):
|
||||
raise ImageError("No disk %s for partition %s" \
|
||||
% (p['disk_name'], p['mountpoint']))
|
||||
|
||||
if p['part_type']:
|
||||
# The --part-type can also be implemented for MBR partitions,
|
||||
# in which case it would map to the 1-byte "partition type"
|
||||
# filed at offset 3 of the partition entry.
|
||||
raise ImageError("setting custom partition type is not " \
|
||||
"implemented for msdos partitions")
|
||||
|
||||
# Get the disk where the partition is located
|
||||
d = self.disks[p['disk_name']]
|
||||
d['numpart'] += 1
|
||||
d['ptable_format'] = ptable_format
|
||||
|
||||
if d['numpart'] == 1:
|
||||
if ptable_format == "msdos":
|
||||
overhead = MBR_OVERHEAD
|
||||
|
||||
# Skip one sector required for the partitioning scheme overhead
|
||||
d['offset'] += overhead
|
||||
# Steal few sectors from the first partition to offset for the
|
||||
# partitioning overhead
|
||||
p['size'] -= overhead
|
||||
|
||||
if p['align']:
|
||||
# If not first partition and we do have alignment set we need
|
||||
# to align the partition.
|
||||
# FIXME: This leaves a empty spaces to the disk. To fill the
|
||||
# gaps we could enlargea the previous partition?
|
||||
|
||||
# Calc how much the alignment is off.
|
||||
align_sectors = d['offset'] % (p['align'] * 1024 / self.sector_size)
|
||||
# We need to move forward to the next alignment point
|
||||
align_sectors = (p['align'] * 1024 / self.sector_size) - align_sectors
|
||||
|
||||
msger.debug("Realignment for %s%s with %s sectors, original"
|
||||
" offset %s, target alignment is %sK." %
|
||||
(p['disk_name'], d['numpart'], align_sectors,
|
||||
d['offset'], p['align']))
|
||||
|
||||
# increase the offset so we actually start the partition on right alignment
|
||||
d['offset'] += align_sectors
|
||||
|
||||
p['start'] = d['offset']
|
||||
d['offset'] += p['size']
|
||||
|
||||
p['type'] = 'primary'
|
||||
p['num'] = d['numpart']
|
||||
|
||||
if d['ptable_format'] == "msdos":
|
||||
if d['numpart'] > 2:
|
||||
# Every logical partition requires an additional sector for
|
||||
# the EBR, so steal the last sector from the end of each
|
||||
# partition starting from the 3rd one for the EBR. This
|
||||
# will make sure the logical partitions are aligned
|
||||
# correctly.
|
||||
p['size'] -= 1
|
||||
|
||||
if d['numpart'] > 3:
|
||||
p['type'] = 'logical'
|
||||
p['num'] = d['numpart'] + 1
|
||||
|
||||
d['partitions'].append(n)
|
||||
msger.debug("Assigned %s to %s%d, sectors range %d-%d size %d "
|
||||
"sectors (%d bytes)." \
|
||||
% (p['mountpoint'], p['disk_name'], p['num'],
|
||||
p['start'], p['start'] + p['size'] - 1,
|
||||
p['size'], p['size'] * self.sector_size))
|
||||
|
||||
# Once all the partitions have been layed out, we can calculate the
|
||||
# minumim disk sizes.
|
||||
for disk_name, d in self.disks.items():
|
||||
d['min_size'] = d['offset']
|
||||
|
||||
d['min_size'] *= self.sector_size
|
||||
|
||||
def __run_parted(self, args):
|
||||
""" Run parted with arguments specified in the 'args' list. """
|
||||
|
||||
args.insert(0, self.parted)
|
||||
msger.debug(args)
|
||||
|
||||
rc, out = runner.runtool(args, catch = 3)
|
||||
out = out.strip()
|
||||
if out:
|
||||
msger.debug('"parted" output: %s' % out)
|
||||
|
||||
if rc != 0:
|
||||
# We don't throw exception when return code is not 0, because
|
||||
# parted always fails to reload part table with loop devices. This
|
||||
# prevents us from distinguishing real errors based on return
|
||||
# code.
|
||||
msger.error("WARNING: parted returned '%s' instead of 0 (use --debug for details)" % rc)
|
||||
|
||||
def __create_partition(self, device, parttype, fstype, start, size):
|
||||
""" Create a partition on an image described by the 'device' object. """
|
||||
|
||||
# Start is included to the size so we need to substract one from the end.
|
||||
end = start + size - 1
|
||||
msger.debug("Added '%s' partition, sectors %d-%d, size %d sectors" %
|
||||
(parttype, start, end, size))
|
||||
|
||||
args = ["-s", device, "unit", "s", "mkpart", parttype]
|
||||
if fstype:
|
||||
args.extend([fstype])
|
||||
args.extend(["%d" % start, "%d" % end])
|
||||
|
||||
return self.__run_parted(args)
|
||||
|
||||
def __format_disks(self):
|
||||
self.layout_partitions()
|
||||
|
||||
for dev in self.disks.keys():
|
||||
d = self.disks[dev]
|
||||
msger.debug("Initializing partition table for %s" % \
|
||||
(d['disk'].device))
|
||||
self.__run_parted(["-s", d['disk'].device, "mklabel",
|
||||
d['ptable_format']])
|
||||
|
||||
msger.debug("Creating partitions")
|
||||
|
||||
for p in self.partitions:
|
||||
d = self.disks[p['disk_name']]
|
||||
if d['ptable_format'] == "msdos" and p['num'] == 5:
|
||||
# The last sector of the 3rd partition was reserved for the EBR
|
||||
# of the first _logical_ partition. This is why the extended
|
||||
# partition should start one sector before the first logical
|
||||
# partition.
|
||||
self.__create_partition(d['disk'].device, "extended",
|
||||
None, p['start'] - 1,
|
||||
d['offset'] - p['start'])
|
||||
|
||||
if p['fstype'] == "swap":
|
||||
parted_fs_type = "linux-swap"
|
||||
elif p['fstype'] == "vfat":
|
||||
parted_fs_type = "fat32"
|
||||
elif p['fstype'] == "msdos":
|
||||
parted_fs_type = "fat16"
|
||||
else:
|
||||
# Type for ext2/ext3/ext4/btrfs
|
||||
parted_fs_type = "ext2"
|
||||
|
||||
# Boot ROM of OMAP boards require vfat boot partition to have an
|
||||
# even number of sectors.
|
||||
if p['mountpoint'] == "/boot" and p['fstype'] in ["vfat", "msdos"] \
|
||||
and p['size'] % 2:
|
||||
msger.debug("Substracting one sector from '%s' partition to " \
|
||||
"get even number of sectors for the partition" % \
|
||||
p['mountpoint'])
|
||||
p['size'] -= 1
|
||||
|
||||
self.__create_partition(d['disk'].device, p['type'],
|
||||
parted_fs_type, p['start'], p['size'])
|
||||
|
||||
if p['boot']:
|
||||
flag_name = "boot"
|
||||
msger.debug("Set '%s' flag for partition '%s' on disk '%s'" % \
|
||||
(flag_name, p['num'], d['disk'].device))
|
||||
self.__run_parted(["-s", d['disk'].device, "set",
|
||||
"%d" % p['num'], flag_name, "on"])
|
||||
|
||||
# Parted defaults to enabling the lba flag for fat16 partitions,
|
||||
# which causes compatibility issues with some firmware (and really
|
||||
# isn't necessary).
|
||||
if parted_fs_type == "fat16":
|
||||
if d['ptable_format'] == 'msdos':
|
||||
msger.debug("Disable 'lba' flag for partition '%s' on disk '%s'" % \
|
||||
(p['num'], d['disk'].device))
|
||||
self.__run_parted(["-s", d['disk'].device, "set",
|
||||
"%d" % p['num'], "lba", "off"])
|
||||
|
||||
def cleanup(self):
|
||||
if self.disks:
|
||||
for dev in self.disks.keys():
|
||||
d = self.disks[dev]
|
||||
try:
|
||||
d['disk'].cleanup()
|
||||
except:
|
||||
pass
|
||||
|
||||
def __write_partition(self, num, source_file, start, size):
|
||||
"""
|
||||
Install source_file contents into a partition.
|
||||
"""
|
||||
if not source_file: # nothing to write
|
||||
return
|
||||
|
||||
# Start is included in the size so need to substract one from the end.
|
||||
end = start + size - 1
|
||||
msger.debug("Installed %s in partition %d, sectors %d-%d, size %d sectors" % (source_file, num, start, end, size))
|
||||
|
||||
dd_cmd = "dd if=%s of=%s bs=%d seek=%d count=%d conv=notrunc" % \
|
||||
(source_file, self.image_file, self.sector_size, start, size)
|
||||
exec_cmd(dd_cmd)
|
||||
|
||||
|
||||
def assemble(self, image_file):
|
||||
msger.debug("Installing partitions")
|
||||
|
||||
self.image_file = image_file
|
||||
|
||||
for p in self.partitions:
|
||||
d = self.disks[p['disk_name']]
|
||||
if d['ptable_format'] == "msdos" and p['num'] == 5:
|
||||
# The last sector of the 3rd partition was reserved for the EBR
|
||||
# of the first _logical_ partition. This is why the extended
|
||||
# partition should start one sector before the first logical
|
||||
# partition.
|
||||
self.__write_partition(p['num'], p['source_file'],
|
||||
p['start'] - 1,
|
||||
d['offset'] - p['start'])
|
||||
|
||||
self.__write_partition(p['num'], p['source_file'],
|
||||
p['start'], p['size'])
|
||||
|
||||
def create(self):
|
||||
for dev in self.disks.keys():
|
||||
d = self.disks[dev]
|
||||
d['disk'].create()
|
||||
|
||||
self.__format_disks()
|
||||
|
||||
return
|
||||
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/python -tt
|
||||
#
|
||||
# Copyright (c) 2011 Intel, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; version 2 of the License
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from wic import msger
|
||||
|
||||
def runtool(cmdln_or_args, catch=1):
|
||||
""" wrapper for most of the subprocess calls
|
||||
input:
|
||||
cmdln_or_args: can be both args and cmdln str (shell=True)
|
||||
catch: 0, quitely run
|
||||
1, only STDOUT
|
||||
2, only STDERR
|
||||
3, both STDOUT and STDERR
|
||||
return:
|
||||
(rc, output)
|
||||
if catch==0: the output will always None
|
||||
"""
|
||||
|
||||
if catch not in (0, 1, 2, 3):
|
||||
# invalid catch selection, will cause exception, that's good
|
||||
return None
|
||||
|
||||
if isinstance(cmdln_or_args, list):
|
||||
cmd = cmdln_or_args[0]
|
||||
shell = False
|
||||
else:
|
||||
import shlex
|
||||
cmd = shlex.split(cmdln_or_args)[0]
|
||||
shell = True
|
||||
|
||||
if catch != 3:
|
||||
dev_null = os.open("/dev/null", os.O_WRONLY)
|
||||
|
||||
if catch == 0:
|
||||
sout = dev_null
|
||||
serr = dev_null
|
||||
elif catch == 1:
|
||||
sout = subprocess.PIPE
|
||||
serr = dev_null
|
||||
elif catch == 2:
|
||||
sout = dev_null
|
||||
serr = subprocess.PIPE
|
||||
elif catch == 3:
|
||||
sout = subprocess.PIPE
|
||||
serr = subprocess.STDOUT
|
||||
|
||||
try:
|
||||
p = subprocess.Popen(cmdln_or_args, stdout=sout,
|
||||
stderr=serr, shell=shell)
|
||||
(sout, serr) = p.communicate()
|
||||
# combine stdout and stderr, filter None out
|
||||
out = ''.join(filter(None, [sout, serr]))
|
||||
except OSError, e:
|
||||
if e.errno == 2:
|
||||
# [Errno 2] No such file or directory
|
||||
msger.error('Cannot run command: %s, lost dependency?' % cmd)
|
||||
else:
|
||||
raise # relay
|
||||
finally:
|
||||
if catch != 3:
|
||||
os.close(dev_null)
|
||||
|
||||
return (p.returncode, out)
|
||||
|
||||
def show(cmdln_or_args):
|
||||
# show all the message using msger.verbose
|
||||
|
||||
rc, out = runtool(cmdln_or_args, catch=3)
|
||||
|
||||
if isinstance(cmdln_or_args, list):
|
||||
cmd = ' '.join(cmdln_or_args)
|
||||
else:
|
||||
cmd = cmdln_or_args
|
||||
|
||||
msg = 'running command: "%s"' % cmd
|
||||
if out: out = out.strip()
|
||||
if out:
|
||||
msg += ', with output::'
|
||||
msg += '\n +----------------'
|
||||
for line in out.splitlines():
|
||||
msg += '\n | %s' % line
|
||||
msg += '\n +----------------'
|
||||
|
||||
msger.verbose(msg)
|
||||
return rc
|
||||
|
||||
def outs(cmdln_or_args, catch=1):
|
||||
# get the outputs of tools
|
||||
return runtool(cmdln_or_args, catch)[1].strip()
|
||||
|
||||
def quiet(cmdln_or_args):
|
||||
return runtool(cmdln_or_args, catch=0)[0]
|
||||
Reference in New Issue
Block a user