#!/usr/bin/env python
# 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.

"""
    Chrome OS bitmap block parser.

    This module helps parsing firmware bitmap blocks so that we can
    retrieve the version and other information from a blob.

    See help(unpack_bmpblock) for more information.

    ref: src/platform/vboot_reference/firmware/include/bmpblk_header.h
"""

import struct
import sys

# Constant Definition
BMPBLOCK_SIGNATURE = "$BMP"
BMPBLOCK_SIGNATURE_SIZE = 4
MAX_IMAGE_IN_LAYOUT = 8

# Blob Structure

# typedef struct BmpBlockHeader {
#   uint8_t signature[BMPBLOCK_SIGNATURE_SIZE];
#   uint16_t major_version;
#   uint16_t minor_version;
#   uint32_t number_of_localizations;
#   uint32_t number_of_screenlayouts;
#   uint32_t number_of_imageinfos;
#   uint32_t locale_string_offset;
#   uint32_t reserved[2];
# };
FORMAT_BMPBLOCK_HEADER = '<4shhIIII2I'
NAMES_BMPBLOCK_HEADER = ('signature',
                         'major_version',
                         'minor_version',
                         'number_of_localizations',
                         'number_of_screenlayouts',
                         'number_of_imageinfos',
                         'locale_string_offset',
                         'reserved')

# typedef struct ScreenLayout {
#   struct {
#     uint32_t x;
#     uint32_t y;
#     uint32_t image_info_offset;
#   } images[MAX_IMAGE_IN_LAYOUT];
# };
FORMAT_SCREEN_LAYOUT_IMAGE = '<III'
NAMES_SCREEN_LAYOUT_IMAGE = ('x', 'y', 'image_info_offset')

# typedef struct ImageInfo {
#   uint32_t tag;
#   uint32_t width;
#   uint32_t height;
#   uint32_t format;
#   uint32_t compression;
#   uint32_t original_size;
#   uint32_t compressed_size;
#   uint32_t reserved;
# };
FORMAT_IMAGE_INFO = '<IIIIIIII'
NAMES_IMAGE_INFO = (
    'tag',
    'width',
    'height',
    'format',
    'compression',
    'original_size',
    'compressed_size',
    'reserved')


def unpack_BmpBlockHeader(blob, offset=0):
  """ Unpacks a BmpBlockHeader from a blob, starting from offset. """
  fields = struct.unpack_from(FORMAT_BMPBLOCK_HEADER, blob, offset)
  header = dict(zip(NAMES_BMPBLOCK_HEADER, fields))
  # check signature
  if header['signature'] != BMPBLOCK_SIGNATURE:
    raise ValueError, 'unknown bmpblock signature: %s' % header['signature']
  return header


def unpack_ImageInfo(blob, offset=0):
  """ Unpacks a ImageInfo from a blob, starting from offset. """
  fields = struct.unpack_from(FORMAT_IMAGE_INFO, blob, offset)
  info = dict(zip(NAMES_IMAGE_INFO, fields))
  return info


def unpack_ScreenLayout(blob, base=0, offset=0):
  """ Unpacks a ScreenLayout from a blob, starting from offset. """
  layout = []
  for index in range(MAX_IMAGE_IN_LAYOUT):
    fields = struct.unpack_from(FORMAT_SCREEN_LAYOUT_IMAGE, blob, offset)
    offset += struct.calcsize(FORMAT_SCREEN_LAYOUT_IMAGE)
    image = dict(zip(NAMES_SCREEN_LAYOUT_IMAGE, fields))
    info_offset = image['image_info_offset']
    if info_offset > 0:
      image.update(unpack_ImageInfo(blob, base + info_offset))
      layout.append(image)
  return layout


def unpack_LocaleString(blob, base=0, offset=0):
  """ Unpacks a double NUL-terminated locale string, starting from offset. """
  end = blob.find('\x00\x00', base + offset)
  if end < 0:
    return []
  locale_string = blob[base + offset:end]
  return locale_string.split('\x00')


def unpack_bmpblock(blob, offset=0):
  """
  Unpacks a Chrome OS Bitmap Block.

  Returns a dictionary of unpacked data
  """
  data = unpack_BmpBlockHeader(blob, offset)
  layout_offset = offset + struct.calcsize(FORMAT_BMPBLOCK_HEADER)
  localizations = []
  for index_locale in range(data['number_of_localizations']):
    layouts = []
    for index_layout in range(data['number_of_screenlayouts']):
      layouts.append(unpack_ScreenLayout(blob, offset, layout_offset))
      layout_offset += (struct.calcsize(FORMAT_SCREEN_LAYOUT_IMAGE) *
                        MAX_IMAGE_IN_LAYOUT)
    localizations.append(layouts)
  data['localizations'] = localizations
  # locale string is optional.
  locale_string_offset = data['locale_string_offset']
  data['locales'] = (unpack_LocaleString(blob, offset, locale_string_offset)
                     if locale_string_offset else [])
  return data


# -----------------------------------------------------------------------------


# When running in command line, try to report blob in the parameters
if __name__ == "__main__":
  # Only load pprint if we are in console (debug / test) mode
  import pprint
  for filename in sys.argv[1:]:
    bmpblk = unpack_bmpblock(open(filename, "rb").read(), 0)
    print pprint.pformat(bmpblk)
