blob: c70af02c85b2ccc781b732124409dfba215df01e [file] [log] [blame]
#!/usr/bin/python -Bu
#
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
from contextlib import nested
import logging
import os
import sys
import factory_common # pylint: disable=W0611
from cros.factory.utils.file_utils import UnopenedTemporaryFile
from cros.factory.utils.process_utils import Spawn
def PreserveSection(fw_main_file, section_file, section_name):
"""Reads out a firmware section.
Args:
fw_main_file: The dummy file served as full firmware image to flashrom.
section_file: The file where the firmware section is saved to.
section_name: The name of the section to read out.
"""
logging.info('Saving %s to %s', section_name, section_file)
Spawn(['flashrom', '-r', fw_main_file, '-i',
'%s:%s' % (section_name, section_file)],
log=True, check_call=True)
def RestoreSection(fw_main_file, section_file, section_name):
"""Writes a firmware section.
Args:
fw_main_file: The dummy file served as full firmware image to flashrom.
section_file: The file containing the data to write.
section_name: The name of the section to write.
"""
logging.info('Restoring %s from %s', section_name, section_file)
Spawn(['flashrom', '-w', fw_main_file, '-i',
'%s:%s' % (section_name, section_file)],
log=True, check_call=True)
def PreserveVPD(fw_main, ro_vpd, rw_vpd):
PreserveSection(fw_main, rw_vpd, 'RW_VPD')
PreserveSection(fw_main, ro_vpd, 'RO_VPD')
def RestoreVPD(fw_main, ro_vpd, rw_vpd):
RestoreSection(fw_main, rw_vpd, 'RW_VPD')
RestoreSection(fw_main, ro_vpd, 'RO_VPD')
def FlashFirmware(fw_image):
logging.info('Flashing firmware %s...', fw_image)
Spawn(['flashrom', '-w', fw_image], log=True, check_call=True)
def main():
parser = argparse.ArgumentParser(
description="Flash netboot firmware with VPD preserved.")
parser.add_argument('--image', '-i', help='Netboot firmware image',
default='/usr/local/factory/custom/netboot.bin',
required=False)
parser.add_argument('--yes', '-y', action='store_true',
help="Don't ask for confirmation")
args = parser.parse_args()
if not os.path.exists(args.image):
parser.error('Firmware image %s does not exist' % args.image)
logging.basicConfig(level=logging.INFO)
sys.stdout.write(
('\n'
'\n'
'*** You are about to flash netboot firmware on this machine with:\n'
'*** %s\n'
'***\n'
'*** This process is unrecoverable and this machine WILL need to\n'
'*** go through network installation again.\n'
'***\n'
'*** Once this process starts, aborting it or powering off the\n'
'*** machine may leave the machine in an unknown state.\n'
'***\n') % args.image)
if not args.yes:
sys.stdout.write('*** Continue? [y/N] ')
answer = sys.stdin.readline()
if not answer or answer[0] not in 'yY':
sys.exit('Aborting.')
with nested(UnopenedTemporaryFile(prefix='fw_main.'),
UnopenedTemporaryFile(prefix='vpd.ro.'),
UnopenedTemporaryFile(prefix='vpd.rw.')) as files:
PreserveVPD(*files)
FlashFirmware(args.image)
RestoreVPD(*files)
if __name__ == '__main__':
main()