#!/usr/bin/env python2.6

# Copyright (c) 2011 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 os
import re
import struct
import subprocess
import sys
import tempfile

# TODO(clchiou): Rewrite this part after official flashmap implementation is
# pulled into Chromium OS code base

# constants imported from lib/fmap.h
FMAP_SIGNATURE = "__FMAP__"
FMAP_VER_MAJOR = 1
FMAP_VER_MINOR = 0
FMAP_STRLEN = 32

FMAP_AREA_STATIC = 1 << 0
FMAP_AREA_COMPRESSED = 1 << 1
FMAP_AREA_RO = 1 << 2

FMAP_HEADER_FORMAT = "<8sBBQI%dsH" % (FMAP_STRLEN)
FMAP_AREA_FORMAT = "<II%dsH" % (FMAP_STRLEN)

FMAP_HEADER_NAMES = (
    'signature',
    'ver_major',
    'ver_minor',
    'base',
    'size',
    'name',
    'nareas',
)

FMAP_AREA_NAMES = (
    'offset',
    'size',
    'name',
    'flags',
)

RE_ASSIGNMENT = re.compile(r'^(\w+)=(.*)$')

VERBOSE = False


class ConfigError(Exception):
  pass


class PackError(Exception):
  pass


class Entry(dict):

  @staticmethod
  def _CheckFields(kwargs, fields):
    for f in fields:
      if f not in kwargs:
        raise ConfigError('Entry: missing required field: %s' % f)

  def __init__(self, **kwargs):
    Entry._CheckFields(kwargs, ('offset', 'length', 'name'))
    super(Entry, self).__init__(kwargs)

  def __getattr__(self, name):
    return self[name]

  def IsOverlapped(self, entry):
    return (entry.offset <= self.offset < entry.offset + entry.length or
            self.offset <= entry.offset < self.offset + self.length)

  def Pack(self, firmware_image, entries):
    raise PackError('class Entry does not implement Pack()')


class EntryFmap(Entry):

  def __init__(self, **kwargs):
    Entry._CheckFields(kwargs, ('ver_major', 'ver_minor', 'base', 'size'))
    super(EntryFmap, self).__init__(**kwargs)

  def Pack(self, firmware_image, entries):
    # prepare header areas
    areas = []
    for e in entries:
      if isinstance(e, EntryFmapArea):
        areas.append(dict((name, e[name] if name != 'size' else e['length'])
                          for name in FMAP_AREA_NAMES))

    # prepare header
    obj = {'areas':areas}
    for name in FMAP_HEADER_NAMES:
      if name == 'nareas':
        v = len(areas)
      elif name == 'signature':
        v = FMAP_SIGNATURE
      else:
        v = self[name]
      obj[name] = v

    blob = fmap_encode(obj)

    if len(blob) > self.length:
        raise PackError('fmap too large: %d > %d' % (len(blob), self.length))

    firmware_image.seek(self.offset)
    firmware_image.write(blob)


class EntryFmapArea(Entry):

  def __init__(self, **kwargs):
    Entry._CheckFields(kwargs, ('flags',))
    super(EntryFmapArea, self).__init__(**kwargs)

  def Pack(self, firmware_image, entries):
    pass


class EntryBlob(EntryFmapArea):

  def __init__(self, **kwargs):
    Entry._CheckFields(kwargs, ('path',))
    super(EntryBlob, self).__init__(**kwargs)

  def Pack(self, firmware_image, entries):
    size = os.stat(self.path).st_size
    if size > self.length:
      raise PackError('blob too large: %s: %d > %d' %
          (self.path, size, self.length))
    if size == 0: # special case for files like /dev/zero
      size = self.length
    with open(self.path, 'rb') as blob_image:
      firmware_image.seek(self.offset)
      firmware_image.write(blob_image.read(size))


class EntryKeyBlock(EntryFmapArea):

  stdout = None
  stderr = None

  def __init__(self, **kwargs):
    Entry._CheckFields(kwargs,
        ('keyblock', 'signprivate', 'version', 'fv', 'kernelkey'))
    super(EntryKeyBlock, self).__init__(**kwargs)
    if VERBOSE:
      EntryKeyBlock.stdout = sys.stdout
      EntryKeyBlock.stderr = sys.stderr

  def Pack(self, firmware_image, entries):
    fd, path = tempfile.mkstemp()
    try:
      args = [
          'vbutil_firmware',
          '--vblock', path,
          '--keyblock', self.keyblock,
          '--signprivate', self.signprivate,
          '--version', '%d' % self.version,
          '--fv', self.fv,
          '--kernelkey', self.kernelkey,
      ]
      _Info('run: %s' % ' '.join(args))
      proc = subprocess.Popen(args,
          stdout=EntryKeyBlock.stdout, stderr=EntryKeyBlock.stderr)
      proc.wait()
      if proc.returncode != 0:
        raise PackError('cannot make key block: vbutil_firmware returns %d' %
			proc.returncode)

      size = os.stat(path).st_size
      if size > self.length:
        raise PackError('key block too large: %d > %d' % (size, self.length))

      with open(path, 'rb') as keyblock_image:
        firmware_image.seek(self.offset)
        firmware_image.write(keyblock_image.read())
    finally:
      os.unlink(path)


# TODO(clchiou): Keep fmap_encode interface compatible with official's flashmap
# implementation, and remove it after it is pulled in.
def fmap_encode(obj):
  def _FormatBlob(format, names, obj):
    return struct.pack(format, *(obj[name] for name in names))
  obj['nareas'] = len(obj['areas'])
  blob = _FormatBlob(FMAP_HEADER_FORMAT, FMAP_HEADER_NAMES, obj)
  for area in obj['areas']:
    blob = blob + _FormatBlob(FMAP_AREA_FORMAT, FMAP_AREA_NAMES, area)
  return blob


def parse_assignment(stmt):
  m = RE_ASSIGNMENT.match(stmt)
  if m is None:
    raise ConfigError('illegal statement: %s' % repr(stmt))
  return (m.group(1), parse_value(m.group(2)))


def parse_value(expr):
  if ((expr.startswith('"') and expr.endswith('"')) or
      (expr.startswith("'") and expr.endswith("'"))):
    return expr[1:-1] # if it is quoted, always interpreted as string literals
  try:
    return int(expr, 0)
  except ValueError:
    return expr # if not a number, interpret as string literals


def pack_firmware_image(entries, output_path, image_size):
  entries = sorted(entries, key=lambda e: e.offset)
  for e1, e2 in zip(entries, entries[1:]):
    # Allow overlap between "pure" fmap areas, but not any of its subclasses
    # Here we exploit the fact that Entry is a new-style class
    if (e1.IsOverlapped(e2) and
        type(e1) is not EntryFmapArea and type(e2) is not EntryFmapArea):
      raise PackError('overlapped entries: [%08x:%08x], [%08x:%08x]' %
          (e1.offset, e1.offset + e1.length, e2.offset, e2.offset + e2.length))

  with open(output_path, 'wb') as firmware_image:
    # resize firmware image file
    firmware_image.seek(0)
    firmware_image.write('\0' * image_size)

    for entry in entries:
      entry.Pack(firmware_image, entries)


def _Info(msg):
  if VERBOSE:
    print >>sys.stderr, 'INFO: %s' % msg


def main():
  global VERBOSE

  if len(sys.argv) < 2:
    print 'Usage: %s [-v] CONFIG_FILE [NAME=VALUE...]' % sys.argv[0]
    sys.exit(1)

  if sys.argv[1] == '-v':
    VERBOSE = True
    argv = sys.argv[0:1] + sys.argv[2:]
  else:
    argv = sys.argv

  if len(argv) > 2:
    env = dict(parse_assignment(stmt) for stmt in argv[2:])
  else:
    env = {}

  execfile(argv[1], globals(), env)

  for varname in ('ENTRIES', 'OUTPUT', 'SIZE'):
    if varname not in env:
      raise ConfigError('undefined variable: %s' % varname)
    _Info('%s = %s' % (varname, repr(env[varname])))

  pack_firmware_image(env['ENTRIES'], env['OUTPUT'], env['SIZE'])

  sys.exit(0)


if __name__ == '__main__':
  main()
