blob: 985b44e52db2abd1121353474b4fc1d4e5009759 [file] [log] [blame]
#!/usr/bin/perl
#
# Copyright Statement:
# --------------------
# This software is protected by Copyright and the information contained
# herein is confidential. The software may not be copied and the information
# contained herein may not be used or disclosed except with the written
# permission of MediaTek Inc. (C) 2013
#
# BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
# NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
# SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
#
# BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
# LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
#
# THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
# WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
# LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
# RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
# THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
#
#
#*****************************************************************************
#*
#* Filename:
#* ---------
#* prepend_gfh.pl
#*
#* Project:
#* --------
#* MOLY
#*
#* Description:
#* ------------
#* Add GFH header for the binary without GFH
#*
#* Author:
#* -------
#* Chin-Chieh Hung (mtk03404)
#*
#****************************************************************************
use strict;
#****************************************************************************
# Included Modules
#****************************************************************************
BEGIN { push @INC, "pcore/" , './LTE_CDP_FMC/Tools/' } # add additional library path
use File::Basename;
use File::Copy;
#use CommonUtility;
#use tools::pack_dep_gen;
#PrintDependModule();
#****************************************************************************
# Constants
#****************************************************************************
my $PREPEND_GFH_VERNO = "m0.05";
# v0.05 by Yu-Hung Huang, add DSP platform id support in m_platform_id instead of hard code to "MT6290"
# v0.04 by Yu-Hung Huang, support don't care flash in m_flash_dev with value FLASH_DEV_NONE (0x00)
# v0.03 by Peiwen Qing, add DSP build time support in m_build_time
# v0.02 by Peiwen Qing, add DSP version support in m_project_id
# v0.01 by mtk03404 Chin-Chieh Hung, initial version
#Usage: prepend_gfh.pl SRC_BINFILE_PATH(filename) DST_BINFILE_PATH(filename) file_info.conf
#****************************************************************************
# Global Variables
#****************************************************************************
my @GFH_Buffer;
my $gfh_fileinfo_type = 1;
my %GFH_FILE_TYPE;
my %GFH_FLASH_DEV;
my %GFH_SIG_TYPE;
#****************************************************************************
# GFH FileInfo Related Enum Definition
#****************************************************************************
$GFH_FILE_TYPE{ "LTE_DSP_ROM" } = chr(0x09).chr(0x01); #Big Endian
$GFH_FLASH_DEV{ "FLASH_DEV_NONE" } = chr(0x00);
$GFH_FLASH_DEV{ "F_NOR" } = chr(0x01);
$GFH_FLASH_DEV{ "F_NAND_SEQUENTIAL" } = chr(0x02);
$GFH_FLASH_DEV{ "F_NAND_TTBL" } = chr(0x03);
$GFH_FLASH_DEV{ "F_NAND_FDM50" } = chr(0x04);
$GFH_FLASH_DEV{ "F_EMMC_BOOT_REGION" } = chr(0x05);
$GFH_FLASH_DEV{ "F_EMMC_DATA_REGION" } = chr(0x06);
$GFH_FLASH_DEV{ "F_SF" } = chr(0x07);
$GFH_FLASH_DEV{ "F_XBOOT" } = chr(0x08);
$GFH_FLASH_DEV{ "FLASH_DEV_END" } = chr(0xFF);
$GFH_SIG_TYPE{ "SIG_NONE" } = chr(0x00);
$GFH_SIG_TYPE{ "SIG_PHASH" } = chr(0x01);
$GFH_SIG_TYPE{ "SIG_SINGLE" } = chr(0x02);
$GFH_SIG_TYPE{ "SIG_SINGLE_AND_PHASE" } = chr(0x03);
$GFH_SIG_TYPE{ "SIG_MULTI" } = chr(0x04);
$GFH_SIG_TYPE{ "SIG_TYPE_NUM" } = chr(0x05);
$GFH_SIG_TYPE{ "SIG_TYPE_END" } = chr(0xFF);
#****************************************************************************
# Input Parameters
#****************************************************************************
my ($src_bin_file) = $ARGV[0];
my ($dst_bin_file) = $ARGV[1];
my ($file_info_cfg) = $ARGV[2];
#****************************************************************************
# Parameter Check
#****************************************************************************
die "source binary file $src_bin_file doesn't exist" if not -e $src_bin_file;
die "config file $file_info_cfg doesn't exist" if not -e $file_info_cfg;
#****************************************************************************
# Functions
#****************************************************************************
if (&IsGFH($src_bin_file))
{
print "The $dst_bin_file has the GFH header, does not prepend the GFH header for $dst_bin_file";
exit 0;
}
else
{
my $b;
my $sum;
my $src_bin_file_size;
open (SRC_FILE_HANDLE, "<$src_bin_file") or &error_handler("$src_bin_file: open file error!");
binmode(SRC_FILE_HANDLE);
while (read(SRC_FILE_HANDLE, $b, 1))
{
$sum .= $b;
}
close SRC_FILE_HANDLE;
open (FILE_HANDLE, ">$dst_bin_file") or &error_handler("$dst_bin_file: open file error!");
$src_bin_file_size = (-s $src_bin_file) + 0x38 + 0xE0;
&GFH_FileInfo_Gen($file_info_cfg, $src_bin_file_size);
&GFH_DSPInfo_Gen($file_info_cfg, 0x38);
binmode(FILE_HANDLE);
print FILE_HANDLE @GFH_Buffer;
print FILE_HANDLE $sum;
close FILE_HANDLE;
#copy($src_bin_file, $dst_bin_file) or die "$!";
}
# GFH_FILE_INFO_v1
# [ 3: 0] GFH_Header.m_magic_ver
# [ 5: 4] GFH_Header.m_size, = size of GFH_FILE_INFO_v1 structure
# [ 7: 6] GFH_Header.m_type, = GFH_FILE_INFO_v1
# [ 19: 8] identifier, = GFH_FILE_INFO_ID = "FILE_INFO"
# [ 23: 20] m_file_ver
# [ 25: 24] m_file_type, = PRI_ROM, DSP_ROM, ...
# [ : 26] m_flash_dev
# [ : 27] m_sig_type
# [ 31: 28] m_load_addr
# [ 35: 32] m_file_len
# [ 39: 36] m_max_size
# [ 43: 40] m_content_offset
# [ 47: 44] m_sig_len
# [ 51: 48] m_jump_offset
# [ 55: 52] m_attr
sub GFH_FileInfo_Gen
{
my ($config_file, $input_file_len) = @_;
my ($nIndex, $data) = (0, undef);
my ($CONFIG_FILE_VER, $CONFIG_FILE_TYPE, $FLASH_DEV, $MAX_SIZE) = &GetFileInfoConfig($config_file);
#GFH_Header.m_magic_ver
$GFH_Buffer[$nIndex++] = 'MMM'; #'M'
$GFH_Buffer[$nIndex++] = chr(0x01);
#GFH_Header.m_size
$GFH_Buffer[$nIndex++] = chr(0x38);
$GFH_Buffer[$nIndex++] = chr(0x00);
#GFH_Header.m_type
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
#identifier
$GFH_Buffer[$nIndex++] = 'FILE_INFO';
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
#m_file_ver
$GFH_Buffer[$nIndex++] = $CONFIG_FILE_VER;
#m_file_type
$GFH_Buffer[$nIndex++] = $GFH_FILE_TYPE{ $CONFIG_FILE_TYPE };
#m_flash_dev
if($FLASH_DEV =~ /_NAND_FLASH_BOOTING_/)
{
$GFH_Buffer[$nIndex++] = $GFH_FLASH_DEV{ "F_NAND_FDM50" };
}
elsif($FLASH_DEV =~ /__EMMC_BOOTING__/)
{
$GFH_Buffer[$nIndex++] = $GFH_FLASH_DEV{ "F_EMMC_DATA_REGION" };
}
elsif($FLASH_DEV =~ /__X_BOOTING__/)
{
$GFH_Buffer[$nIndex++] = $GFH_FLASH_DEV{ "F_XBOOT" };
}
elsif($FLASH_DEV =~ /__SERIAL_FLASH_EN__/)
{
$GFH_Buffer[$nIndex++] = $GFH_FLASH_DEV{ "F_SF" };
}
elsif($FLASH_DEV =~ /__DONT_CARE_FLASH__/)
{
$GFH_Buffer[$nIndex++] = $GFH_FLASH_DEV{ "FLASH_DEV_NONE" };
}
else
{
$GFH_Buffer[$nIndex++] = $GFH_FLASH_DEV{ "F_NOR" };
}
#m_sig_type
$GFH_Buffer[$nIndex++] = $GFH_SIG_TYPE{ "SIG_NONE" };
#m_load_addr
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
#m_file_len
$GFH_Buffer[$nIndex++] = &Dec2ASCIIString($input_file_len);
#m_max_size
$GFH_Buffer[$nIndex++] = &Dec2ASCIIString($MAX_SIZE);
#m_content_offset
$GFH_Buffer[$nIndex++] = chr(0x18);
$GFH_Buffer[$nIndex++] = chr(0x01);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
#m_sig_len
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
#m_jump_offset
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
#m_attr, no XIP in MT6290, default value is 0
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
print pack("i*", @GFH_Buffer);
}
# GFH_DSP_INFO_v1
# [ 3: 0] GFH_Header.m_magic_ver
# [ 5: 4] GFH_Header.m_size = size of GFH_FILE_INFO_v1 structure
# [ 7: 6] GFH_Header.m_type = GFH_FILE_INFO_v1
# [ 11: 8] m_product_ver = 0x1 // 0x0: invalid, 0x1: debug version (DSP image not encrypted), 0x2: release version
# [ 15: 12] m_image_type // 0x0: invalid, 0x1: normal image, 0x2: RFC flavor image
# [ 31: 16] m_platform_id[16] // ex: "MT6290_S00", "MT6290_S01", "MT6595_S00"
# [ 95: 32] m_project_id[64] // ex: "DSPMOLY.W13.21.LTE.p6"
# [159: 96] m_build_time // ex: "24\10\2013 17:50:29"
# [223: 160] reserved
sub GFH_DSPInfo_Gen
{
my ($config_file, $nIndex) = @_;
my ($PLATFORM_ID, $VERSION, $BUILD_TIME) = &GetDSPInfoConfig($config_file);
my ($counter);
#GFH_Header.m_magic_ver
$GFH_Buffer[$nIndex++] = 'MMM'; #'M'
$GFH_Buffer[$nIndex++] = chr(0x01);
#GFH_Header.m_size
$GFH_Buffer[$nIndex++] = chr(0xE0);
$GFH_Buffer[$nIndex++] = chr(0x00);
#GFH_Header.m_type
$GFH_Buffer[$nIndex++] = chr(0x04);
$GFH_Buffer[$nIndex++] = chr(0x01);
#m_product_ver
$GFH_Buffer[$nIndex++] = chr(0x01);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
#m_image_type
$GFH_Buffer[$nIndex++] = chr(0x00); #why not 1??
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
$GFH_Buffer[$nIndex++] = chr(0x00);
#m_platform_id
if (length($PLATFORM_ID) > 16)
{
print "The platform ID strings exceed the max string size 16!";
exit 0;
}
$GFH_Buffer[$nIndex++] = $PLATFORM_ID;
for ($counter = length($PLATFORM_ID) + 1; $counter <= 16; $counter++)
{
$GFH_Buffer[$nIndex++] = chr(0x00);
}
#m_project_id
if (length($VERSION) > 64)
{
print "The project ID strings exceed the max string size 64!";
exit 0;
}
$GFH_Buffer[$nIndex++] = $VERSION;
for ($counter = length($VERSION) + 1; $counter <= 64; $counter++)
{
$GFH_Buffer[$nIndex++] = chr(0x00);
}
#m_build_time
if (length($BUILD_TIME) > 64)
{
print "The build time strings exceed the max string size 64!";
exit 0;
}
$GFH_Buffer[$nIndex++] = $BUILD_TIME;
for ($counter = length($BUILD_TIME) + 1; $counter <= 64; $counter++)
{
$GFH_Buffer[$nIndex++] = chr(0x00);
}
#reserved
for (0..63)
{
$GFH_Buffer[$nIndex++] = chr(0x00);
}
print pack("i*", @GFH_Buffer);
}
#****************************************************************************
# subroutine: Get file config
# input: config file
# output: File Info config setting
#****************************************************************************
sub GetFileInfoConfig
{
my $fileContent = &GetFileContent(@_);
my $parse_file_ver;
my $parse_file_ver_str;
my $parse_file_type;
my $parse_flash_dev;
my $parse_max_size;
$fileContent =~ s/(.*)#(.*)/$1/g;
$fileContent =~ /FILE_VER:[ \f\t]*(\w*)[ \f\t]*/;
$parse_file_ver = hex($1);
$parse_file_ver_str = &Dec2ASCIIString($parse_file_ver);
$fileContent =~ /FILE_TYPE:[ \f\t]*(\w*)[ \f\t]*/;
$parse_file_type = $1;
$fileContent =~ /FLASH_DEV:[ \f\t]*(\w*)[ \f\t]*/;
$parse_flash_dev = $1;
$fileContent =~ /MAX_SIZE:[ \f\t]*(\w*)[ \f\t]*/;
$parse_max_size = hex($1);
return ($parse_file_ver_str, $parse_file_type, $parse_flash_dev, $parse_max_size);
}
#****************************************************************************
# subroutine: Get dsp config
# input: config file
# output: DSP Info config setting
#****************************************************************************
sub GetDSPInfoConfig
{
my $fileContent = &GetFileContent(@_);
my $platform_id;
my $parse_version;
my $build_time;
$fileContent =~ s/(.*)#(.*)/$1/g;
$fileContent =~ /PLATFORM_ID:[ \f\t]*(.*)[ \f\t]*/;
$platform_id = $1;
$fileContent =~ /VERSION:[ \f\t]*(.*)[ \f\t]*/;
$parse_version = $1;
$fileContent =~ /BUILD_TIME:[ \f\t]*(.*)[ \f\t]*/;
$build_time = $1;
return ($platform_id, $parse_version, $build_time);
}
#****************************************************************************
# subroutine: GetFileContent
# input: strFilePath
# output: strFileContent after chomp
#****************************************************************************
sub GetFileContent
{
my ($strFilePath) = @_;
my $content;
open FILE, "<$strFilePath" or &error_handler("$strFilePath: open file error!", __FILE__, __LINE__, 'CommonUtil::GetFileContent');
{
local $/;
$content = <FILE>;
}
close FILE;
chomp($content);
return $content;
}
#****************************************************************************
# subroutine: Dec2HexASCII, without "0x" for prefix, big endian
# input: Integer value
# output: Hex ASCII without "0x"
#****************************************************************************
sub Dec2ASCIIString
{
my ($dec) = @_;
my $str = "";
if ($dec > 0x00FF0000)
{
$str .= chr(($dec >> 0) & 0xFF);
$str .= chr(($dec >> 8) & 0xFF);
$str .= chr(($dec >> 16) & 0xFF);
$str .= chr(($dec >> 24) & 0xFF);
}
elsif($dec > 0x0000FF00)
{
$str .= chr($dec & 0xFF);
$str .= chr(($dec >> 8) & 0xFF);
$str .= chr(($dec >> 16) & 0xFF);
$str .= chr(0x00);
}
elsif($dec > 0x000000FF)
{
$str .= chr($dec & 0xFF);
$str .= chr(($dec >> 8) & 0xFF);
$str .= chr(0x00);
$str .= chr(0x00);
}
else
{
$str .= chr($dec & 0xFF);
$str .= chr(0x00);
$str .= chr(0x00);
$str .= chr(0x00);
}
}
#****************************************************************************
# subroutine: Check GFH Header, (0-2: 4D 4D 4D, 8-16: FILE_INFO)
# input: File Name
# output: True/False
#****************************************************************************
sub IsGFH
{
my ($strFilePath) = @_;
my $bIsGFH = 0;
if (-e $strFilePath)
{
# Get 17bytes (0-2: 4D 4D 4D, 8-16: FILE_INFO
open (FILE_HANDLE, "<$strFilePath") or &error_handler("$strFilePath: open file error!");
#binmode(FILE_HANDLE);
my ($nIndex, $data) = (0, undef);
my @Buffer;
while (read(FILE_HANDLE, $data, 1))
{
$Buffer[$nIndex++] = $data;
last if ($nIndex > 16);
}
close FILE_HANDLE;
my ($strFILE_INFO, $nMatchMMM) = (undef, 0);
for (0..2)
{
$nMatchMMM++ if (ord($Buffer[$_]) == 0x4D);
}
for (8..16)
{
$strFILE_INFO .= $Buffer[$_];
}
$bIsGFH =1 if($nMatchMMM == 3 and $strFILE_INFO eq "FILE_INFO");
}
return $bIsGFH;
}
#****************************************************************************
# subroutine: error_handler
# input: $error_msg: error message
# $file: filename
# $line_no: line number
#****************************************************************************
sub error_handler
{
my ($error_msg) = @_;
my ($pack_name, $file, $line_no) = caller;
my $final_error_msg = "PREPEND_GFH ERROR: $error_msg at $file line $line_no\n";
die $final_error_msg;
}