Merge "ginstall: Add support for Android images"
diff --git a/ginstall/ginstall.py b/ginstall/ginstall.py
index f03dfa3..67f196a 100755
--- a/ginstall/ginstall.py
+++ b/ginstall/ginstall.py
@@ -62,10 +62,13 @@
F = {
'ETCPLATFORM': '/etc/platform',
+ 'ETCOS': '/etc/os',
'ETCVERSION': '/etc/version',
'DEV': '/dev',
'MMCBLK0': '/dev/mmcblk0',
+ 'MMCBLK0-ANDROID': '/dev/block/mmcblk0',
'MTD_PREFIX': '/dev/mtd',
+ 'MTD_PREFIX-ANDROID': '/dev/mtd/mtd',
'PROC_CMDLINE': '/proc/cmdline',
'PROC_MTD': '/proc/mtd',
'SECUREBOOT': '/tmp/gpio/ledcontrol/secure_boot',
@@ -74,12 +77,22 @@
'SYSBLOCK': '/sys/block',
'MMCBLK0BOOT0': '/dev/mmcblk0boot0',
'MMCBLK0BOOT1': '/dev/mmcblk0boot1',
+ 'MMCBLK0BOOT0-ANDROID': '/dev/block/mmcblk0boot0',
+ 'MMCBLK0BOOT1-ANDROID': '/dev/block/mmcblk0boot1',
'MEMINFO': '/proc/meminfo',
}
+ANDROID_BSU_PARTITION = 'bsu'
+ANDROID_BOOT_PARTITIONS = ['boot_a', 'boot_b']
+ANDROID_SYSTEM_PARTITIONS = ['system_a', 'system_b']
+ANDROID_IMAGES = ['boot.img', 'system.img.raw']
+ANDROID_IMG_SUFFIX = ['a', 'b']
+
MMC_RO_LOCK = {
'MMCBLK0BOOT0': '/sys/block/mmcblk0boot0/force_ro',
'MMCBLK0BOOT1': '/sys/block/mmcblk0boot1/force_ro',
+ 'MMCBLK0BOOT0-ANDROID': '/sys/block/mmcblk0boot0/force_ro',
+ 'MMCBLK0BOOT1-ANDROID': '/sys/block/mmcblk0boot1/force_ro',
}
# Verbosity of output
@@ -131,6 +144,26 @@
return open(F['ETCPLATFORM']).read().strip()
+def GetOs():
+ # not all platforms provide ETCOS, default to 'fiberos' in that case
+ try:
+ return open(F['ETCOS']).read().strip()
+ except IOError:
+ return 'fiberos'
+
+
+def GetMtdPrefix():
+ if GetOs() == 'android':
+ return F['MTD_PREFIX-ANDROID']
+ return F['MTD_PREFIX']
+
+
+def GetMmcblk0Prefix():
+ if GetOs() == 'android':
+ return F['MMCBLK0-ANDROID']
+ return F['MMCBLK0']
+
+
def GetVersion():
return open(F['ETCVERSION']).read().strip()
@@ -154,17 +187,47 @@
return None
-def SetBootPartition(partition):
- VerbosePrint('Setting boot partition to kernel%d\n', partition)
- cmd = [HNVRAM, '-q', '-w', 'ACTIVATED_KERNEL_NAME=kernel%d' % partition]
- return subprocess.call(cmd)
+def SetBootPartition(target_os, partition):
+ """Set active boot partition for the given OS and switch the OS if needed.
+
+ Args:
+ target_os: 'fiberos' or 'android'
+ partition: 0 or 1
+
+ Returns:
+ 0 if successful, else an error code.
+ """
+ if target_os == 'android':
+ param = 'ANDROID_ACTIVE_PARTITION=%s' % ANDROID_IMG_SUFFIX[partition]
+ else:
+ param = 'ACTIVATED_KERNEL_NAME=kernel%d' % partition
+
+ VerbosePrint('Setting boot partition: %s\n', param)
+ try:
+ ret = subprocess.call([HNVRAM, '-q', '-w', param])
+ except OSError:
+ ret = 127
+ if ret:
+ VerbosePrint('Failed setting boot partition!\n')
+ return ret
+
+ if target_os != GetOs():
+ VerbosePrint('Switch OS to %s\n', target_os)
+ try:
+ ret = subprocess.call([HNVRAM, '-q', '-w', 'BOOT_TARGET=%s' % target_os])
+ except OSError:
+ ret = 127
+ if ret:
+ VerbosePrint('Failed switching OS!\n')
+
+ return ret
def GetBootedPartition():
"""Get the role of partition where the running system is booted from.
Returns:
- 0 or 1 for rootfs0 and rootfs1, or None if not booted from flash.
+ 0 or 1, or None if not booted from flash.
"""
try:
with open(F['PROC_CMDLINE']) as f:
@@ -184,6 +247,41 @@
return 0
elif partition == 'kernel1':
return 1
+ elif arg.startswith('androidboot.gfiber_system_img='):
+ partition = arg.split('=')[1]
+ if partition == ANDROID_SYSTEM_PARTITIONS[0]:
+ return 0
+ elif partition == ANDROID_SYSTEM_PARTITIONS[1]:
+ return 1
+ return None
+
+
+def GetActivePartitionFromHNVRAM(target_os):
+ """Get the active partion for the given OS as set in HNVRAM.
+
+ Args:
+ target_os: 'fiberos' or 'android'
+
+ Returns:
+ 0 or 1 if the active partition could be determined, None if not.
+ """
+ if target_os == 'fiberos':
+ cmd = [HNVRAM, '-q', '-r', 'ACTIVATED_KERNEL_NAME']
+ elif target_os == 'android':
+ cmd = [HNVRAM, '-q', '-r', 'ANDROID_ACTIVE_PARTITION']
+ else:
+ return None
+
+ try:
+ partition_name = subprocess.check_output(cmd).strip()
+ except subprocess.CalledProcessError:
+ return None
+
+ if partition_name in ['0', 'a']:
+ return 0
+ elif partition_name in ['1', 'b']:
+ return 1
+
return None
@@ -219,12 +317,12 @@
if len(fields) >= 4 and fields[3] == quotedname:
assert fields[0].startswith('mtd')
assert fields[0].endswith(':')
- return '%s%d' % (F['MTD_PREFIX'], int(fields[0][3:-1]))
+ return '%s%d' % (GetMtdPrefix(), int(fields[0][3:-1]))
return None # no match
def IsMtdNand(mtddevname):
- mtddevname = re.sub(r'^' + F['MTD_PREFIX'], 'mtd', mtddevname)
+ mtddevname = re.sub(r'^' + GetMtdPrefix(), 'mtd', mtddevname)
path = F['SYSCLASSMTD'] + '/{0}/type'.format(mtddevname)
data = open(path).read()
return 'nand' in data
@@ -275,7 +373,8 @@
Returns:
Device file of named partition
"""
- cmd = [SGDISK, '-p', blk_dev]
+ # Note: Android doesn't support '-p' option, need to use '--print'
+ cmd = [SGDISK, '--print', blk_dev]
devnull = open('/dev/null', 'w')
try:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=devnull)
@@ -641,6 +740,24 @@
return True
+def GetOsFromManifest(manifest):
+ """Determine which OS (FiberOS, Android) the image is for from the manifest.
+
+ Args:
+ manifest: the manifest from an image file
+
+ Returns:
+ 'android' if any Android specific image name is found in the manifest,
+ otherwise it returns 'fiberos' (default).
+
+ """
+ for key in manifest.keys():
+ if key.endswith('-sha1'):
+ if key[:-5] in ANDROID_IMAGES:
+ return 'android'
+ return 'fiberos'
+
+
class ProgressBar(object):
"""Progress bar that prints one dot per 1MB."""
@@ -695,26 +812,37 @@
Log('W: psback/logos unavailable for tracing.\n')
-def GetPartition(opt):
- """Return the partiton to install to, given the command line options."""
- if opt.partition == 'other':
- boot = GetBootedPartition()
+def GetPartition(partition_name, target_os):
+ """Return the partition to install to.
+
+ Args:
+ partition_name: partition name from command-line
+ {'primary', 'secondary', 'other'}
+ target_os: 'fiberos' or 'android'
+
+ Returns:
+ 0 or 1
+
+ Raises:
+ Fatal: if no partition could be determined
+ """
+ if partition_name == 'other':
+ if target_os == GetOs():
+ boot = GetBootedPartition()
+ else:
+ boot = GetActivePartitionFromHNVRAM(target_os)
assert boot in [None, 0, 1]
if boot is None:
# Policy decision: if we're booted from NFS, install to secondary
return 1
else:
return boot ^ 1
- elif opt.partition in ['primary', 0]:
+ elif partition_name in ['primary', 0]:
return 0
- elif opt.partition in ['secondary', 1]:
+ elif partition_name in ['secondary', 1]:
return 1
- elif opt.partition:
- raise Fatal('--partition must be one of: primary, secondary, other')
- elif opt.tar:
- raise Fatal('A --partition option must be provided with --tar')
else:
- return None
+ raise Fatal('--partition must be one of: primary, secondary, other')
def InstallKernel(kern, partition):
@@ -729,7 +857,7 @@
partition_name = 'kernel%d' % partition
mtd = GetMtdDevForNameOrNone(partition_name)
- gpt = GetGptPartitionForName(F['MMCBLK0'], partition_name)
+ gpt = GetGptPartitionForName(GetMmcblk0Prefix(), partition_name)
if mtd:
VerbosePrint('Writing kernel to %r\n' % mtd)
InstallToMtd(kern, mtd)
@@ -759,7 +887,7 @@
if gpt:
mtd = None
else:
- gpt = GetGptPartitionForName(F['MMCBLK0'], partition_name)
+ gpt = GetGptPartitionForName(GetMmcblk0Prefix(), partition_name)
if mtd:
if GetPlatform().startswith('GFMN'):
VerbosePrint('Writing rootfs to %r\n' % mtd)
@@ -775,6 +903,72 @@
raise Fatal('no partition named %r is available' % partition_name)
+def InstallAndroidBoot(boot, partition):
+ """Install an Android boot.img file.
+
+ Args:
+ boot: a FileWithSecureHash object.
+ partition: the partition to install to, 0 or 1.
+
+ Raises:
+ Fatal: if install fails
+ """
+
+ partition_name = ANDROID_BOOT_PARTITIONS[partition]
+ gpt = GetGptPartitionForName(GetMmcblk0Prefix(), partition_name)
+ if gpt:
+ VerbosePrint('Writing boot.img to %r\n' % gpt)
+ InstallToFile(boot, gpt)
+ else:
+ raise Fatal('no partition named %r is available' % partition_name)
+
+
+def InstallAndroidSystem(system, partition):
+ """Install an Android system.img file.
+
+ Args:
+ system: a FileWithSecureHash object.
+ partition: the partition to install to, 0 or 1.
+
+ Raises:
+ Fatal: if install fails
+ """
+
+ partition_name = ANDROID_SYSTEM_PARTITIONS[partition]
+ gpt = GetGptPartitionForName(GetMmcblk0Prefix(), partition_name)
+ if gpt:
+ VerbosePrint('Writing system.img.raw to %r\n' % gpt)
+ InstallToFile(system, gpt)
+ else:
+ raise Fatal('no partition named %r is available' % partition_name)
+
+
+def InstallAndroidBsu(bsu):
+ """Install an Android BSU file.
+
+ Args:
+ bsu: a FileWithSecureHash object.
+
+ Raises:
+ Fatal: if install fails
+ """
+
+ is_bsu_current = False
+ gpt = GetGptPartitionForName(GetMmcblk0Prefix(), ANDROID_BSU_PARTITION)
+ if gpt:
+ with open(gpt, 'rb') as gptfile:
+ VerbosePrint('Checking if android_bsu is up to date.\n')
+ is_bsu_current = IsIdentical('android_bsu', bsu.filelike, gptfile)
+ if is_bsu_current:
+ VerbosePrint('android_bsu is the latest.\n')
+ else:
+ bsu.filelike.seek(0, os.SEEK_SET)
+ VerbosePrint('Writing android_bsu.elf to %r\n' % gpt)
+ InstallToFile(bsu, gpt)
+ else:
+ raise Fatal('no partition named %r is available' % ANDROID_BSU_PARTITION)
+
+
def UnlockMMC(mmc_name):
if mmc_name in MMC_RO_LOCK:
with open(MMC_RO_LOCK[mmc_name], 'w') as f:
@@ -805,7 +999,11 @@
WriteLoaderToMtd(loader, loader_start, mtd, 'loader')
installed = True
# For hd254 we also write the loader to the emmc boot partitions.
- for emmc_name in ['MMCBLK0BOOT0', 'MMCBLK0BOOT1']:
+ if GetOs() == 'android':
+ emmc_list = ['MMCBLK0BOOT0-ANDROID', 'MMCBLK0BOOT1-ANDROID']
+ else:
+ emmc_list = ['MMCBLK0BOOT0', 'MMCBLK0BOOT1']
+ for emmc_name in emmc_list:
emmc_dev = F[emmc_name]
if os.path.exists(emmc_dev):
UnlockMMC(emmc_name)
@@ -843,19 +1041,23 @@
WriteLoaderToMtd(uloader, uloader_start, mtd, 'uloader')
-def InstallImage(f, partition, skiploader=False, skiploadersig=False):
+def InstallImage(opt):
"""Install an image.
Args:
- f: a file-like objected expected to provide a stream in tar format
- partition: integer 0 or 1 of the partition to install into
- skiploader: skip installation of a bootloader
- skiploadersig: skip checking of bootloader signature
+ opt: command-line options
+ Returns:
+ 0 for success, else an error code
Raises:
Fatal: if install fails
"""
+ if not opt.partition:
+ # default to the safe option if not given
+ opt.partition = 'other'
+
+ f = OpenPathOrUrl(opt.tar)
tar = tarfile.open(mode='r|*', fileobj=f)
first = tar.next()
@@ -879,13 +1081,16 @@
CheckMinimumVersion(manifest)
CheckMisc(manifest)
+ target_os = GetOsFromManifest(manifest)
+ partition = GetPartition(opt.partition, target_os)
+
loader_bin_list = ['loader.img', 'loader.bin']
loader_sig_list = ['loader.sig']
if CheckMultiLoader(manifest):
loader_bin_list = ['loader.%s.bin' % GetPlatform().lower()]
loader_sig_list = ['loader.%s.sig' % GetPlatform().lower()]
- uloader = loader = None
+ uloader = loader = android_bsu = None
uloadersig = FileWithSecureHash(StringIO.StringIO(''), 'badsig')
# TODO(cgibson): Modern ginstall images contain a loadersig. However, some
@@ -907,11 +1112,29 @@
# already processed
pass
elif ti.name in ['kernel.img', 'vmlinuz', 'vmlinux', 'uImage']:
- fh = FileWithSecureHash(tar.extractfile(ti), secure_hash)
- InstallKernel(fh, partition)
+ if target_os != 'fiberos':
+ VerbosePrint('Cannot install kernel img in Android!\n')
+ else:
+ fh = FileWithSecureHash(tar.extractfile(ti), secure_hash)
+ InstallKernel(fh, partition)
elif ti.name.startswith('rootfs.'):
- fh = FileWithSecureHash(tar.extractfile(ti), secure_hash)
- InstallRootfs(fh, partition)
+ if target_os != 'fiberos':
+ VerbosePrint('Cannot install rootfs img in Android!\n')
+ else:
+ fh = FileWithSecureHash(tar.extractfile(ti), secure_hash)
+ InstallRootfs(fh, partition)
+ elif ti.name == 'boot.img':
+ if target_os != 'android':
+ VerbosePrint('Cannot install boot img in FiberOS!\n')
+ else:
+ fh = FileWithSecureHash(tar.extractfile(ti), secure_hash)
+ InstallAndroidBoot(fh, partition)
+ elif ti.name == 'system.img.raw':
+ if target_os != 'android':
+ VerbosePrint('Cannot install system img in FiberOS!\n')
+ else:
+ fh = FileWithSecureHash(tar.extractfile(ti), secure_hash)
+ InstallAndroidSystem(fh, partition)
elif ti.name in loader_bin_list:
buf = StringIO.StringIO(tar.extractfile(ti).read())
loader = FileWithSecureHash(buf, secure_hash)
@@ -924,34 +1147,49 @@
elif ti.name == 'uloader.sig':
buf = StringIO.StringIO(tar.extractfile(ti).read())
uloadersig = FileWithSecureHash(buf, secure_hash)
+ elif ti.name == 'android_bsu.elf':
+ buf = StringIO.StringIO(tar.extractfile(ti).read())
+ android_bsu = FileWithSecureHash(buf, secure_hash)
else:
print 'Unknown install file %s' % ti.name
- if skiploadersig:
+ if opt.skiploadersig:
loadersig = uloadersig = None
key = GetKey()
- if loadersig and loader and not skiploader:
+ if loadersig and loader and not opt.skiploader:
if not Verify(loader.filelike, loadersig.filelike, key):
raise Fatal('Loader signing check failed.')
loader.filelike.seek(0, os.SEEK_SET)
- if uloadersig and uloader and not skiploader:
+ if uloadersig and uloader and not opt.skiploader:
if not Verify(uloader.filelike, uloadersig.filelike, key):
raise Fatal('Uloader signing check failed.')
uloader.filelike.seek(0, os.SEEK_SET)
if loader:
- if skiploader:
+ if opt.skiploader:
VerbosePrint('Skipping loader installation.\n')
else:
InstallLoader(loader)
if uloader:
- if skiploader:
+ if opt.skiploader:
VerbosePrint('Skipping uloader installation.\n')
else:
InstallUloader(uloader)
+ if android_bsu:
+ if opt.skiploader:
+ VerbosePrint('Skipping android_bsu installation.\n')
+ else:
+ InstallAndroidBsu(android_bsu)
+
+ if SetBootPartition(target_os, partition) != 0:
+ VerbosePrint('Unable to set boot partition\n')
+ return HNVRAM_ERR
+
+ return 0
+
def OpenPathOrUrl(path):
"""Try to open path as a URL and as a local file."""
@@ -980,6 +1218,16 @@
if not (opt.drm or opt.tar or opt.partition):
o.fatal('Expected at least one of --partition, --tar, or --drm')
+ # handle 'ginstall -p <partition>' separately
+ if not opt.drm and not opt.tar:
+ partition = GetPartition(opt, GetOs())
+ if SetBootPartition(GetOs(), partition) != 0:
+ VerbosePrint('Unable to set boot partition\n')
+ return HNVRAM_ERR
+ return 0
+
+ # from here: ginstall [-t <tarfile>] [--drm <blob>] [options...]
+
quiet = opt.quiet
if opt.basepath:
@@ -989,21 +1237,11 @@
if opt.drm:
WriteDrm(opt)
- if opt.tar and not opt.partition:
- # default to the safe option if not given
- opt.partition = 'other'
-
- partition = GetPartition(opt)
+ ret = 0
if opt.tar:
- f = OpenPathOrUrl(opt.tar)
- InstallImage(f, partition, skiploader=opt.skiploader,
- skiploadersig=opt.skiploadersig)
+ ret = InstallImage(opt)
- if partition is not None and SetBootPartition(partition) != 0:
- VerbosePrint('Unable to set boot partition\n')
- return HNVRAM_ERR
-
- return 0
+ return ret
def BroadcomDeviceIsSecure():
diff --git a/ginstall/ginstall_test.py b/ginstall/ginstall_test.py
index 07cb294..5b335ea 100755
--- a/ginstall/ginstall_test.py
+++ b/ginstall/ginstall_test.py
@@ -40,13 +40,16 @@
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
+ self.hnvram_dir = self.tmpdir + '/hnvram'
self.script_out = self.tmpdir + '/out'
self.old_path = os.environ['PATH']
self.old_bufsize = ginstall.BUFSIZE
self.old_files = ginstall.F
+ os.environ['GINSTALL_HNVRAM_DIR'] = self.hnvram_dir
os.environ['GINSTALL_OUT_FILE'] = self.script_out
os.environ['GINSTALL_TEST_FAIL'] = ''
os.environ['PATH'] = 'testdata/bin:' + self.old_path
+ os.makedirs(self.hnvram_dir)
os.makedirs(self.tmpdir + '/dev')
ginstall.F['ETCPLATFORM'] = 'testdata/etc/platform'
ginstall.F['DEV'] = self.tmpdir + '/dev'
@@ -69,6 +72,9 @@
ginstall.MMC_RO_LOCK['MMCBLK0BOOT1'] = (
self.tmpdir + '/mmcblk0boot1/force_ro')
+ # default OS to 'fiberos'
+ self.WriteOsFile('fiberos')
+
def tearDown(self):
os.environ['PATH'] = self.old_path
shutil.rmtree(self.tmpdir, ignore_errors=True)
@@ -80,6 +86,23 @@
open(filename, 'w').write(version)
ginstall.F['ETCVERSION'] = filename
+ def WriteOsFile(self, os_name):
+ """Create a fake /etc/os file in /tmp."""
+ filename = self.tmpdir + '/os'
+ open(filename, 'w').write(os_name)
+ ginstall.F['ETCOS'] = filename
+
+ def WriteHnvramAttr(self, attr, val):
+ filename = self.hnvram_dir + '/%s' % attr
+ open(filename, 'w').write(val)
+
+ def ReadHnvramAttr(self, attr):
+ filename = self.hnvram_dir + '/%s' % attr
+ try:
+ return open(filename).read()
+ except IOError:
+ return None
+
def testVerify(self):
self.assertTrue(ginstall.Verify(
open('testdata/img/loader.bin'),
@@ -158,11 +181,44 @@
origfile, 'mtd0.tmp')
def testSetBootPartition(self):
- ginstall.SetBootPartition(0)
- ginstall.SetBootPartition(1)
+ self.WriteOsFile('fiberos')
+ ginstall.SetBootPartition('fiberos', 0)
+ self.assertEqual('kernel0', self.ReadHnvramAttr('ACTIVATED_KERNEL_NAME'))
+ ginstall.SetBootPartition('fiberos', 1)
+ self.assertEqual('kernel1', self.ReadHnvramAttr('ACTIVATED_KERNEL_NAME'))
+ ginstall.SetBootPartition('android', 0)
+ self.assertEqual('a', self.ReadHnvramAttr('ANDROID_ACTIVE_PARTITION'))
+ self.assertEqual('android', self.ReadHnvramAttr('BOOT_TARGET'))
+ ginstall.SetBootPartition('android', 1)
+ self.assertEqual('b', self.ReadHnvramAttr('ANDROID_ACTIVE_PARTITION'))
+ self.assertEqual('android', self.ReadHnvramAttr('BOOT_TARGET'))
+
+ self.WriteOsFile('android')
+ ginstall.SetBootPartition('fiberos', 0)
+ self.assertEqual('kernel0', self.ReadHnvramAttr('ACTIVATED_KERNEL_NAME'))
+ self.assertEqual('fiberos', self.ReadHnvramAttr('BOOT_TARGET'))
+ ginstall.SetBootPartition('fiberos', 1)
+ self.assertEqual('kernel1', self.ReadHnvramAttr('ACTIVATED_KERNEL_NAME'))
+ self.assertEqual('fiberos', self.ReadHnvramAttr('BOOT_TARGET'))
+ ginstall.SetBootPartition('android', 0)
+ self.assertEqual('a', self.ReadHnvramAttr('ANDROID_ACTIVE_PARTITION'))
+ ginstall.SetBootPartition('android', 1)
+ self.assertEqual('b', self.ReadHnvramAttr('ANDROID_ACTIVE_PARTITION'))
+
+ # also verify the hnvram command history for good measures
out = open(self.script_out).read().splitlines()
self.assertEqual(out[0], 'hnvram -q -w ACTIVATED_KERNEL_NAME=kernel0')
self.assertEqual(out[1], 'hnvram -q -w ACTIVATED_KERNEL_NAME=kernel1')
+ self.assertEqual(out[2], 'hnvram -q -w ANDROID_ACTIVE_PARTITION=a')
+ self.assertEqual(out[3], 'hnvram -q -w BOOT_TARGET=android')
+ self.assertEqual(out[4], 'hnvram -q -w ANDROID_ACTIVE_PARTITION=b')
+ self.assertEqual(out[5], 'hnvram -q -w BOOT_TARGET=android')
+ self.assertEqual(out[6], 'hnvram -q -w ACTIVATED_KERNEL_NAME=kernel0')
+ self.assertEqual(out[7], 'hnvram -q -w BOOT_TARGET=fiberos')
+ self.assertEqual(out[8], 'hnvram -q -w ACTIVATED_KERNEL_NAME=kernel1')
+ self.assertEqual(out[9], 'hnvram -q -w BOOT_TARGET=fiberos')
+ self.assertEqual(out[10], 'hnvram -q -w ANDROID_ACTIVE_PARTITION=a')
+ self.assertEqual(out[11], 'hnvram -q -w ANDROID_ACTIVE_PARTITION=b')
def testParseManifest(self):
l = ('installer_version: 99\nimage_type: fake\n'
@@ -189,6 +245,34 @@
manifest = ginstall.ParseManifest(in_f)
self.assertTrue(ginstall.CheckPlatform(manifest))
+ def testGetOs(self):
+ self.WriteOsFile('fiberos')
+ self.assertEqual('fiberos', ginstall.GetOs())
+ self.WriteOsFile('android')
+ self.assertEqual('android', ginstall.GetOs())
+ # in case file doesn't exist, default is 'fiberos'
+ os.remove(self.tmpdir + '/os')
+ self.assertEqual('fiberos', ginstall.GetOs())
+
+ def testGetMtdPrefix(self):
+ self.WriteOsFile('fiberos')
+ self.assertEqual(ginstall.F['MTD_PREFIX'], ginstall.GetMtdPrefix())
+ self.WriteOsFile('android')
+ self.assertEqual(ginstall.F['MTD_PREFIX-ANDROID'], ginstall.GetMtdPrefix())
+ # unknown OS returns 'fiberos'
+ self.WriteOsFile('windows')
+ self.assertEqual(ginstall.F['MTD_PREFIX'], ginstall.GetMtdPrefix())
+
+ def testGetMmcblk0Prefix(self):
+ self.WriteOsFile('fiberos')
+ self.assertEqual(ginstall.F['MMCBLK0'], ginstall.GetMmcblk0Prefix())
+ self.WriteOsFile('android')
+ self.assertEqual(ginstall.F['MMCBLK0-ANDROID'],
+ ginstall.GetMmcblk0Prefix())
+ # unknown OS returns 'fiberos'
+ self.WriteOsFile('windows')
+ self.assertEqual(ginstall.F['MMCBLK0'], ginstall.GetMmcblk0Prefix())
+
def testGetInternalHarddisk(self):
self.assertEqual(ginstall.GetInternalHarddisk(), None)
@@ -268,20 +352,141 @@
manifest = {'version': v}
self.assertRaises(ginstall.Fatal, ginstall.CheckMisc, manifest)
- def testGetBootedFromCmdLine(self):
- ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline1'
+ def MakeManifestWithFilenameSha1s(self, filename):
+ m = ('installer_version: 4\n'
+ 'image_type: unlocked\n'
+ 'version: gftv254-48-pre2-1100-g25ff8d0-ck\n'
+ 'platforms: [ GFHD254 ]\n')
+ if filename is not None:
+ m += '%s-sha1: 9b5236c282b8c11b38a630361b6c690d6aaa50cb\n' % filename
+
+ in_f = StringIO.StringIO(m)
+ return ginstall.ParseManifest(in_f)
+
+ def testGetOsFromManifest(self):
+ # android specific image names return 'android'
+ for img in ginstall.ANDROID_IMAGES:
+ manifest = self.MakeManifestWithFilenameSha1s(img)
+ self.assertEqual('android', ginstall.GetOsFromManifest(manifest))
+
+ # fiberos image names or anything non-android returns 'fiberos'
+ for img in ['rootfs.img', 'kernel.img', 'whatever.img']:
+ manifest = self.MakeManifestWithFilenameSha1s(img)
+ self.assertEqual('fiberos', ginstall.GetOsFromManifest(manifest))
+
+ # no sha1 entry in the manifest returns 'fiberos'
+ manifest = self.MakeManifestWithFilenameSha1s(None)
+ self.assertEqual('fiberos', ginstall.GetOsFromManifest(manifest))
+
+ def testGetBootedPartition(self):
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.none'
+ self.assertEqual(None, ginstall.GetBootedPartition())
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.0'
+ self.assertEqual(0, ginstall.GetBootedPartition())
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.1'
+ self.assertEqual(1, ginstall.GetBootedPartition())
+
+ # Android
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.android.none'
+ self.assertEqual(None, ginstall.GetBootedPartition())
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.android.0'
+ self.assertEqual(0, ginstall.GetBootedPartition())
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.android.1'
+ self.assertEqual(1, ginstall.GetBootedPartition())
+
+ # Prowl
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.prowl.none'
self.assertEqual(ginstall.GetBootedPartition(), None)
- ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline2'
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.prowl.0'
self.assertEqual(ginstall.GetBootedPartition(), 0)
- ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline3'
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.prowl.1'
self.assertEqual(ginstall.GetBootedPartition(), 1)
+ def testGetActivePartitionFromHNVRAM(self):
+ # FiberOS looks at ACTIVATED_KERNEL_NAME, not ANDROID_ACTIVE_PARTITION
+ # 0
+ self.WriteHnvramAttr('ACTIVATED_KERNEL_NAME', '0')
+ self.assertEqual(0, ginstall.GetActivePartitionFromHNVRAM('fiberos'))
+ self.WriteHnvramAttr('ANDROID_ACTIVE_PARTITION', '0')
+ self.assertEqual(0, ginstall.GetActivePartitionFromHNVRAM('fiberos'))
+ self.WriteHnvramAttr('ANDROID_ACTIVE_PARTITION', '1')
+ self.assertEqual(0, ginstall.GetActivePartitionFromHNVRAM('fiberos'))
+ # 1
+ self.WriteHnvramAttr('ACTIVATED_KERNEL_NAME', '1')
+ self.assertEqual(1, ginstall.GetActivePartitionFromHNVRAM('fiberos'))
+ self.WriteHnvramAttr('ANDROID_ACTIVE_PARTITION', '0')
+ self.assertEqual(1, ginstall.GetActivePartitionFromHNVRAM('fiberos'))
+
+ # Android looks at ANDROID_ACTIVE_PARTITION, not ACTIVATED_KERNEL_NAME
+ # 0
+ self.WriteHnvramAttr('ANDROID_ACTIVE_PARTITION', '0')
+ self.assertEqual(0, ginstall.GetActivePartitionFromHNVRAM('android'))
+ self.WriteHnvramAttr('ACTIVATED_KERNEL_NAME', '0')
+ self.assertEqual(0, ginstall.GetActivePartitionFromHNVRAM('android'))
+ self.WriteHnvramAttr('ACTIVATED_KERNEL_NAME', '1')
+ self.assertEqual(0, ginstall.GetActivePartitionFromHNVRAM('android'))
+ # 1
+ self.WriteHnvramAttr('ANDROID_ACTIVE_PARTITION', '1')
+ self.assertEqual(1, ginstall.GetActivePartitionFromHNVRAM('android'))
+ self.WriteHnvramAttr('ACTIVATED_KERNEL_NAME', '0')
+ self.assertEqual(1, ginstall.GetActivePartitionFromHNVRAM('android'))
+
+ def TestGetPartition(self):
+ self.assertEqual(0, ginstall.GetPartition('primary', 'fiberos'))
+ self.assertEqual(0, ginstall.GetPartition(0, 'fiberos'))
+ self.assertEqual(1, ginstall.GetPartition('secondary', 'fiberos'))
+ self.assertEqual(1, ginstall.GetPartition(1, 'fiberos'))
+ self.assertEqual(0, ginstall.GetPartition('primary', 'android'))
+ self.assertEqual(0, ginstall.GetPartition(0, 'android'))
+ self.assertEqual(1, ginstall.GetPartition('secondary', 'android'))
+ self.assertEqual(1, ginstall.GetPartition(1, 'android'))
+
+ # other: FiberOS->FiberOS
+ self.WriteOsFile('fiberos')
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.none'
+ self.assertEqual(1, ginstall.GetPartition('other', 'fiberos'))
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.0'
+ self.assertEqual(1, ginstall.GetPartition('other', 'fiberos'))
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.1'
+ self.assertEqual(0, ginstall.GetPartition('other', 'fiberos'))
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.prowl.none'
+ self.assertEqual(1, ginstall.GetPartition('other', 'fiberos'))
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.prowl.0'
+ self.assertEqual(1, ginstall.GetPartition('other', 'fiberos'))
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.prowl.1'
+ self.assertEqual(0, ginstall.GetPartition('other', 'fiberos'))
+
+ # other: FiberOS->Android
+ self.WriteHnvramAttr('ANDROID_ACTIVE_PARTITION', 'a')
+ self.assertEqual(1, ginstall.GetPartition('other', 'android'))
+ self.WriteHnvramAttr('ANDROID_ACTIVE_PARTITION', 'b')
+ self.assertEqual(0, ginstall.GetPartition('other', 'android'))
+ self.WriteHnvramAttr('ANDROID_ACTIVE_PARTITION', 'bla')
+ self.assertEqual(1, ginstall.GetPartition('other', 'android'))
+
+ # other: Android->FiberOS
+ self.WriteOsFile('android')
+ self.WriteHnvramAttr('ACTIVATED_KERNEL_NAME', '0')
+ self.assertEqual(1, ginstall.GetPartition('other', 'fiberos'))
+ self.WriteHnvramAttr('ACTIVATED_KERNEL_NAME', '1')
+ self.assertEqual(0, ginstall.GetPartition('other', 'fiberos'))
+ self.WriteHnvramAttr('ACTIVATED_KERNEL_NAME', 'bla')
+ self.assertEqual(1, ginstall.GetPartition('other', 'fiberos'))
+
+ # other: Android->Android
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.android.none'
+ self.assertEqual(1, ginstall.GetPartition('other', 'android'))
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.android.0'
+ self.assertEqual(1, ginstall.GetPartition('other', 'android'))
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.android.1'
+ self.assertEqual(0, ginstall.GetPartition('other', 'android'))
+
# Test prowl and gfactive
- ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline4'
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.prowl.none'
self.assertEqual(ginstall.GetBootedPartition(), None)
- ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline5'
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.prowl.0'
self.assertEqual(ginstall.GetBootedPartition(), 0)
- ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline6'
+ ginstall.F['PROC_CMDLINE'] = 'testdata/proc/cmdline.prowl.1'
self.assertEqual(ginstall.GetBootedPartition(), 1)
def testUloaderSigned(self):
diff --git a/ginstall/install_test.sh b/ginstall/install_test.sh
index ec372c5..910971d 100755
--- a/ginstall/install_test.sh
+++ b/ginstall/install_test.sh
@@ -4,20 +4,29 @@
tmpdir="$(mktemp -d)"
export PATH="$tmpdir/bin:${PATH}"
+export GINSTALL_HNVRAM_DIR="$tmpdir/hnvram"
export GINSTALL_OUT_FILE="$tmpdir/out"
+export GINSTALL_PLATFORM_FILE="$tmpdir/etc/platform"
psiz=$(stat --format=%s testdata/img/loader.gflt110.bin)
lsiz=$(stat --format=%s testdata/img/loader.img)
ksiz=$(stat --format=%s testdata/img/kernel.img)
rsiz=$(stat --format=%s testdata/img/rootfs.img)
usiz=$(stat --format=%s testdata/img/uloader.img)
+bsiz=$(stat --format=%s testdata/img/boot.img)
+ssiz=$(stat --format=%s testdata/img/system.img.raw)
+asiz=$(stat --format=%s testdata/img/android_bsu.elf)
testdata/bin/http_server "$tmpdir/http_ctrl" &
setup_fakeroot() {
platform="$1"
+ running_os="fiberos"
+ [ $# -gt 1 ] && running_os="$2"
rm -f "$GINSTALL_OUT_FILE"
rm -rf "$tmpdir/*"
mkdir -p "$tmpdir/bin" "$tmpdir/dev" "$tmpdir/etc"
+ mkdir -p "$tmpdir/dev/block" "$tmpdir/dev/mtd"
mkdir -p "$tmpdir/sys/block/sda"
+ mkdir -p "$GINSTALL_HNVRAM_DIR"
cp -r testdata/bin "$tmpdir"
cp -r testdata/proc "$tmpdir"
cp -r testdata/img "$tmpdir"
@@ -30,10 +39,18 @@
echo 0123456789abcdef0123456789abcdef >"$tmpdir/dev/mtd3"
echo 0123456789abcdef0123456789abcdef >"$tmpdir/dev/mtd4"
+ # write a pre-existing android_bsu
+ echo 0123456789abcdef0123456789abcdef >"$tmpdir/dev/mmcblk0p2"
+ echo 0123456789abcdef0123456789abcdef >"$tmpdir/dev/block/mmcblk0p2"
+
for i in {5..31}; do touch "$tmpdir/dev/mtd$i"; done
+ # duplicate /dev/mtd* to /dev/mtd/mtd* (used by Android)
+ cp ${tmpdir}/dev/mtd[0-9]* ${tmpdir}/dev/mtd/
+
cp "testdata/proc/mtd.$platform" "$tmpdir/proc/mtd"
echo "$platform" >"$tmpdir/etc/platform"
+ echo "$running_os" >"$tmpdir/etc/os"
echo 0123456789abcdef0123456789abcdef >"$tmpdir/etc/gfiber_public.der"
}
@@ -150,6 +167,74 @@
+# kernel in NAND, raw no bbt
+# rootfs on eMMC
+# (GFHD254)
+echo; echo; echo "GFHD254 (fiberos->fiberos)"
+setup_fakeroot GFHD254 fiberos
+expected="\
+psback
+logos ginstall
+flash_erase --quiet ${tmpdir}/dev/mtd0 0 0
+hnvram -q -w ACTIVATED_KERNEL_NAME=kernel1"
+
+WVPASS ./ginstall.py --basepath="$tmpdir" --tar=./testdata/img/image_v4.gi --partition=secondary --skiploadersig
+WVPASSEQ "$expected" "$(cat $GINSTALL_OUT_FILE)"
+WVPASS cmp --bytes="$lsiz" "${tmpdir}/dev/mtd0" testdata/img/loader.img
+WVPASS cmp --bytes="$ksiz" "${tmpdir}/dev/mmcblk0p14" testdata/img/kernel.img
+WVPASS cmp --bytes="$rsiz" "${tmpdir}/dev/mmcblk0p15" testdata/img/rootfs.img
+
+# FiberOS->Android (GFHD254)
+echo; echo; echo "GFHD254 (fiberos->android)"
+setup_fakeroot GFHD254 fiberos
+expected="\
+psback
+logos ginstall
+flash_erase --quiet ${tmpdir}/dev/mtd0 0 0
+hnvram -q -w ANDROID_ACTIVE_PARTITION=b
+hnvram -q -w BOOT_TARGET=android"
+
+WVPASS ./ginstall.py --basepath="$tmpdir" --tar=./testdata/img/image_android_v4.gi --partition=secondary --skiploadersig
+WVPASSEQ "$expected" "$(cat $GINSTALL_OUT_FILE)"
+WVPASS cmp --bytes="$lsiz" "${tmpdir}/dev/mtd0" testdata/img/loader.img
+WVPASS cmp --bytes="$asiz" "${tmpdir}/dev/mmcblk0p2" testdata/img/android_bsu.elf
+WVPASS cmp --bytes="$bsiz" "${tmpdir}/dev/mmcblk0p6" testdata/img/boot.img
+WVPASS cmp --bytes="$ssiz" "${tmpdir}/dev/mmcblk0p10" testdata/img/system.img.raw
+
+# Android->Android (GFHD254)
+echo; echo; echo "GFHD254 (android->android)"
+setup_fakeroot GFHD254 android
+expected="\
+psback
+logos ginstall
+flash_erase --quiet ${tmpdir}/dev/mtd/mtd0 0 0
+hnvram -q -w ANDROID_ACTIVE_PARTITION=a"
+
+WVPASS ./ginstall.py --basepath="$tmpdir" --tar=./testdata/img/image_android_v4.gi --partition=primary --skiploadersig
+WVPASSEQ "$expected" "$(cat $GINSTALL_OUT_FILE)"
+WVPASS cmp --bytes="$lsiz" "${tmpdir}/dev/mtd/mtd0" testdata/img/loader.img
+WVPASS cmp --bytes="$asiz" "${tmpdir}/dev/block/mmcblk0p2" testdata/img/android_bsu.elf
+WVPASS cmp --bytes="$bsiz" "${tmpdir}/dev/block/mmcblk0p5" testdata/img/boot.img
+WVPASS cmp --bytes="$ssiz" "${tmpdir}/dev/block/mmcblk0p9" testdata/img/system.img.raw
+
+# Android->FiberOS (GFHD254)
+echo; echo; echo "GFHD254 (android->fiberos)"
+setup_fakeroot GFHD254 android
+expected="\
+psback
+logos ginstall
+flash_erase --quiet ${tmpdir}/dev/mtd/mtd0 0 0
+hnvram -q -w ACTIVATED_KERNEL_NAME=kernel0
+hnvram -q -w BOOT_TARGET=fiberos"
+
+WVPASS ./ginstall.py --basepath="$tmpdir" --tar=./testdata/img/image_v4.gi --partition=primary --skiploadersig
+WVPASSEQ "$expected" "$(cat $GINSTALL_OUT_FILE)"
+WVPASS cmp --bytes="$lsiz" "${tmpdir}/dev/mtd/mtd0" testdata/img/loader.img
+WVPASS cmp --bytes="$ksiz" "${tmpdir}/dev/block/mmcblk0p12" testdata/img/kernel.img
+WVPASS cmp --bytes="$rsiz" "${tmpdir}/dev/block/mmcblk0p13" testdata/img/rootfs.img
+
+
+
# kernel in NOR, raw
# rootfs in NOR, raw
# loader in NOR, raw
diff --git a/ginstall/testdata/bin/hnvram b/ginstall/testdata/bin/hnvram
deleted file mode 120000
index 3c2bde7..0000000
--- a/ginstall/testdata/bin/hnvram
+++ /dev/null
@@ -1 +0,0 @@
-write_args_to_file
\ No newline at end of file
diff --git a/ginstall/testdata/bin/hnvram b/ginstall/testdata/bin/hnvram
new file mode 100755
index 0000000..6faa2b6
--- /dev/null
+++ b/ginstall/testdata/bin/hnvram
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# log into out file
+exe=$(basename "$0")
+echo "$exe" $* >> "$GINSTALL_OUT_FILE"
+
+# simple cmdline parser
+for i in "$@"; do
+ if [ "$i" == "-q" ]; then
+ continue
+ elif [ "$i" == "-r" ]; then
+ read=1
+ elif [ "$i" == "-w" ]; then
+ write=1
+ else
+ attr_val="$i"
+ fi
+done
+
+IFS='=' read attr val <<< "$attr_val"
+
+GINSTALL_ATTR_FILE="${GINSTALL_HNVRAM_DIR}/${attr}"
+
+if [ -n "$write" ]; then
+ echo -n "$val" > "$GINSTALL_ATTR_FILE"
+elif [ -n "$read" ]; then
+ if [ ! -r "$GINSTALL_ATTR_FILE" ]; then
+ exit 1
+ else
+ cat "$GINSTALL_ATTR_FILE"
+ fi
+fi
+
+if [ ! -z "$GINSTALL_TEST_FAIL" ]; then
+ exit 1
+fi
+
+exit 0
diff --git a/ginstall/testdata/bin/sgdisk b/ginstall/testdata/bin/sgdisk
index 69c640f..7e9392a 100755
--- a/ginstall/testdata/bin/sgdisk
+++ b/ginstall/testdata/bin/sgdisk
@@ -1,6 +1,6 @@
#!/bin/sh
-echo "Disk /dev/mmcblk0: 7634944 sectors, 3.6 GiB
+default="Disk /dev/mmcblk0: 7634944 sectors, 3.6 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF
Partition table holds up to 128 entries
@@ -15,3 +15,37 @@
19 954368 1740799 384.0 MiB FFFF rootfs1
20 1740800 1871871 64.0 MiB FFFF emergency
21 1871872 7114751 2.5 GiB 8300 data+ext4"
+
+gfhd254="Disk /dev/mmcblk0: 61071360 sectors, 29.1 GiB
+Logical sector size: 512 bytes
+Disk identifier (GUID): BE51F469-09A6-4A05-9A3B-D09855D3E5A1
+Partition table holds up to 128 entries
+First usable sector is 34, last usable sector is 61071326
+Partitions will be aligned on 2-sector boundaries
+Total free space is 0 sectors (0 bytes)
+
+Number Start (sector) End (sector) Size Code Name
+ 1 34 161 64.0 KiB 8300 nvram
+ 2 162 673 256.0 KiB 8300 bsu
+ 3 674 2721 1024.0 KiB 8300 misc
+ 4 2722 4769 1024.0 KiB 8300 hwcfg
+ 5 4770 70305 32.0 MiB 8300 boot_a
+ 6 70306 135841 32.0 MiB 8300 boot_b
+ 7 135842 152225 8.0 MiB 8300 metadata
+ 8 152226 156321 2.0 MiB 8300 eio
+ 9 156322 4350625 2.0 GiB 8300 system_a
+ 10 4350626 8544929 2.0 GiB 8300 system_b
+ 11 8544930 8547873 1.4 MiB 8300 hnvram
+ 12 8547874 8613409 32.0 MiB 8300 kernel0
+ 13 8613410 9399841 384.0 MiB 8300 rootfs0
+ 14 9399842 9465377 32.0 MiB 8300 kernel1
+ 15 9465378 10251809 384.0 MiB 8300 rootfs1
+ 16 10251810 10382881 64.0 MiB 8300 emergency
+ 17 10382882 61071326 24.2 GiB 8300 userdata"
+
+platform="$(cat $GINSTALL_PLATFORM_FILE)"
+if [ "$platform" == "GFHD254" ]; then
+ echo "$gfhd254"
+else
+ echo "$default"
+fi
diff --git a/ginstall/testdata/img/MANIFEST b/ginstall/testdata/img/MANIFEST
index de8c93b..5e839f4 100644
--- a/ginstall/testdata/img/MANIFEST
+++ b/ginstall/testdata/img/MANIFEST
@@ -1,7 +1,7 @@
installer_version: 4
image_type: unittest
version: gftv200-40.1
-platforms: [ GFUNITTEST, GFSC100, GFMN100, GFHD200, GFHD100, GFMS100, GFRG210, GFRG200 ]
+platforms: [ GFUNITTEST, GFSC100, GFMN100, GFHD200, GFHD254, GFHD100, GFMS100, GFRG210, GFRG200 ]
loader.img-sha1: 228d83f86ba967704a94afce92e1e4cbba3b24a6
uloader.img-sha1: 171e9a2e524c1f3a64f43ef7d254b85e764f1096
kernel.img-sha1: fbd0ad4af43303c6b3001920689db2eb4d5212d0
diff --git a/ginstall/testdata/img/android_bsu.elf b/ginstall/testdata/img/android_bsu.elf
new file mode 100644
index 0000000..44687e7
--- /dev/null
+++ b/ginstall/testdata/img/android_bsu.elf
@@ -0,0 +1 @@
+android_bsu.elf
\ No newline at end of file
diff --git a/ginstall/testdata/img/boot.img b/ginstall/testdata/img/boot.img
new file mode 100644
index 0000000..7afe48a
--- /dev/null
+++ b/ginstall/testdata/img/boot.img
@@ -0,0 +1 @@
+boot.img
\ No newline at end of file
diff --git a/ginstall/testdata/img/image_android_v4.gi b/ginstall/testdata/img/image_android_v4.gi
new file mode 100644
index 0000000..601138a
--- /dev/null
+++ b/ginstall/testdata/img/image_android_v4.gi
Binary files differ
diff --git a/ginstall/testdata/img/image_v4.gi b/ginstall/testdata/img/image_v4.gi
index 11aac14..7d66211 100644
--- a/ginstall/testdata/img/image_v4.gi
+++ b/ginstall/testdata/img/image_v4.gi
Binary files differ
diff --git a/ginstall/testdata/img/system.img.raw b/ginstall/testdata/img/system.img.raw
new file mode 100644
index 0000000..3fcfe41
--- /dev/null
+++ b/ginstall/testdata/img/system.img.raw
@@ -0,0 +1 @@
+system.img.raw
\ No newline at end of file
diff --git a/ginstall/testdata/proc/cmdline2 b/ginstall/testdata/proc/cmdline.0
similarity index 100%
rename from ginstall/testdata/proc/cmdline2
rename to ginstall/testdata/proc/cmdline.0
diff --git a/ginstall/testdata/proc/cmdline3 b/ginstall/testdata/proc/cmdline.1
similarity index 100%
rename from ginstall/testdata/proc/cmdline3
rename to ginstall/testdata/proc/cmdline.1
diff --git a/ginstall/testdata/proc/cmdline.android.0 b/ginstall/testdata/proc/cmdline.android.0
new file mode 100644
index 0000000..8fb7943
--- /dev/null
+++ b/ginstall/testdata/proc/cmdline.android.0
@@ -0,0 +1 @@
+mem=1024m@0m mem=1024m@2048m bmem=336m@672m bmem=256m@2048m brcm_cma=768m@2304m ramoops.mem_address=0x3F800000 ramoops.mem_size=0x800000 ramoops.console_size=0x400000 pmem=8m@1016m androidboot.selinux=permissive androidboot.hardware=gfhd254 androidboot.gfiber_system_img=system_a bootreason=main_chip_input
diff --git a/ginstall/testdata/proc/cmdline.android.1 b/ginstall/testdata/proc/cmdline.android.1
new file mode 100644
index 0000000..4da7328
--- /dev/null
+++ b/ginstall/testdata/proc/cmdline.android.1
@@ -0,0 +1 @@
+mem=1024m@0m mem=1024m@2048m bmem=336m@672m bmem=256m@2048m brcm_cma=768m@2304m ramoops.mem_address=0x3F800000 ramoops.mem_size=0x800000 ramoops.console_size=0x400000 pmem=8m@1016m androidboot.selinux=permissive androidboot.hardware=gfhd254 bootreason=main_chip_input androidboot.gfiber_system_img=system_b
diff --git a/ginstall/testdata/proc/cmdline.android.none b/ginstall/testdata/proc/cmdline.android.none
new file mode 100644
index 0000000..9fb507c
--- /dev/null
+++ b/ginstall/testdata/proc/cmdline.android.none
@@ -0,0 +1 @@
+mem=1024m@0m mem=1024m@2048m bmem=336m@672m bmem=256m@2048m brcm_cma=768m@2304m ramoops.mem_address=0x3F800000 ramoops.mem_size=0x800000 ramoops.console_size=0x400000 pmem=8m@1016m androidboot.selinux=permissive androidboot.hardware=gfhd254 bootreason=main_chip_input
diff --git a/ginstall/testdata/proc/cmdline1 b/ginstall/testdata/proc/cmdline.none
similarity index 100%
rename from ginstall/testdata/proc/cmdline1
rename to ginstall/testdata/proc/cmdline.none
diff --git a/ginstall/testdata/proc/cmdline5 b/ginstall/testdata/proc/cmdline.prowl.0
similarity index 100%
rename from ginstall/testdata/proc/cmdline5
rename to ginstall/testdata/proc/cmdline.prowl.0
diff --git a/ginstall/testdata/proc/cmdline6 b/ginstall/testdata/proc/cmdline.prowl.1
similarity index 100%
rename from ginstall/testdata/proc/cmdline6
rename to ginstall/testdata/proc/cmdline.prowl.1
diff --git a/ginstall/testdata/proc/cmdline4 b/ginstall/testdata/proc/cmdline.prowl.none
similarity index 100%
rename from ginstall/testdata/proc/cmdline4
rename to ginstall/testdata/proc/cmdline.prowl.none
diff --git a/ginstall/testdata/proc/mtd.GFHD254 b/ginstall/testdata/proc/mtd.GFHD254
new file mode 100644
index 0000000..21616d1
--- /dev/null
+++ b/ginstall/testdata/proc/mtd.GFHD254
@@ -0,0 +1,3 @@
+dev: size erasesize name
+mtd0: 00400000 00001000 "flash0.bolt"
+mtd1: 00400000 00001000 "flash0"