blob: 34fa86efbe55382763e35cbae60c34d9674dc9d7 [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) 2006
#
# 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:
#* ---------
#* ckSysDrv.pl
#*
#* Project:
#* --------
#* Maui_Software
#*
#* Description:
#* ------------
#* This script parse prepocessed fs_quota.c and nvram_user_config.c to
#* 1. check if system drive space is enough
#* 2. display current flash usage
#*
#* Author:
#* -------
#* Sherman Wang (mtk00590)
#*
#*============================================================================
#* HISTORY
#* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
#*------------------------------------------------------------------------------
#* $Revision: $
#* $Modtime: $
#* $Log: $
#*
#*
#*------------------------------------------------------------------------------
#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
#*============================================================================
#****************************************************************************/
#****************************************************************************
# Included Modules
#****************************************************************************
BEGIN { push @INC , './tools/' } # add additional library path
use strict;
use Getopt::Std;
use POSIX;
use auto_adjust_mem; # pm file name without case sensitivity
use constant OWNER => "mtk02704";
#****************************************************************************
# Constants
#****************************************************************************
my $DebugPrint = 0;
# 0001(1)
# 0010(2)
# 0100(4): NVRAM/Quota handling details
# 1000(8): NVRAM/Quota
#****************************************************************************
# Usage
#****************************************************************************
sub usage
{
print "perl ckSysDrv.pl <Preprocessed fs_quota.c> <Preprocessed nvram_user_config.c>\n";
exit(0);
}
#****************************************************************************
# parsing command arguments
#****************************************************************************
my %option = ();
if (!getopts('hdc:', \%option) or $option{'h'})
{
&usage;
exit(0);
}
$DebugPrint = 1 if $option{'d'};
my $FLASH_CFG = $ARGV[0];
my $FS_STAT = $ARGV[1];
my $NVRAM_STAT = $ARGV[2];
my $FEATURE_OVERLOAD = $ARGV[3];
my $SYSTEM_DRIVE_ON_NAND = $ARGV[4];
my $NVRAM_PSEUDO_MERGE = $ARGV[5];
my $BOARD_FOLDER = $ARGV[6];
my $LINK_INFO = $ARGV[7];
my $PROJECT = $ARGV[8];
my $AAPMCLOG = $ARGV[9];
my %cluster_multiple = ();
print "[CkSysDrv] Starting...\n" if ($DebugPrint & 1);
print "[CkSysDrv] ARGV# = $#ARGV\n" if($DebugPrint & 1);
my $j = 0;
my %arguments = (
0 => "\$FLASH_CFG",
1 => "\$FS_STAT",
2 => "\$NVRAM_STAT",
3 => "\$FEATURE_OVERLOAD",
4 => "\$SYSTEM_DRIVE_ON_NAND",
5 => "\$NVRAM_PSEUDO_MERGE",
6 => "\$BOARD_FOLDER",
7 => "\$LINK_INFO",
8 => "\$PROJECT",
9 => "\$AAPMCLOG",
);
for (; $j < $#ARGV + 1 ; $j++)
{
printf("\t\t\$ARGV[$j]: $arguments{$j} = %s\n", $ARGV[$j]) if($DebugPrint & 1);
}
#****************************************************************************
# Parse preprocessed custom_MemoryDevice.h and custom_EMI.h
#****************************************************************************
open(FLASH_CFG, "<$FLASH_CFG") or cksysdrv_die(ERR::ERR_UNEXPECTED, "cannot open FLASH_CFG: $FLASH_CFG\n", __FILE__, __LINE__);
my $backup = $/;
undef $/;
my $reading = <FLASH_CFG>;
close FLASH_CFG;
# common variables
my $fs_auto_config_support;
my $allocated_fat_space; # in Byte
my $first_partition_sectors; # in Sector
my $first_partition_size; # in Byte
my $system_drive_sectors; # in Sector
my $system_drive_size; # in Byte
my $flash_base_address;
my $system_drive_location;
my $ON_NAND = 1;
my $ON_NOR = 2;
my $ON_EMMC = 3;
my $app_storage_in_sys_drv;
my $original_base_address;
my $original_fat_space;
my $original_first_partition_sectors;
my $free_space = -1;
my $cksysdrv_enabled;
my $DEV_PREFIX; # prefix of macros in custom_MemoryDevice.h
my $DEV_TYPE; # memory type of debug info
# NOR flash specific variables
my $fs_low_cost_support;
my $nvram_custom_cfg_max_record_sector_num;
my $nor_regions;
my $nor_reserved_blocks;
my $nor_single_bank_support = 0;
my $nor_sector_size;
my $nor_max_blk_size = 0; # in Byte
my $nor_drive_overhead = 0; # in Byte
my $blockheader_overhead = 0;
my $blockheader_overhead_total = 0;
my $nor_min_reserved_blocks = 2;
my $nor_extra_reserved_space = 0;
my $nor_extra_reserved_space_for_power_loss = 0;
my $nor_protection_mode_reserved_space = 0;
# NAND flash specific variables
my $nand_block_size; # KB
my $fat_nand_block_num;
my $nand_log_block_num;
my $fat_nand_region_num;
my $nand_fdm_version;
#
my $code_boundary_addr=0; #in Byte
my $release_all_free = -1; #flag
my $alignment; #in Byte
my $code_shortage_size;
my $short_block;
my $short_block_size;
my $diff;
my $cluster_size; # in Byte
# log
my @log_buf = ();
my %error_code = (
ERR::NO_MODIFY => "ERR::NO_MODIFY",
ERR::MODIFY_SUCCESS => "ERR::MODIFY_SUCCESS",
ERR::CANNOT_ADJUST => "ERR::CANNOT_ADJUST",
ERR::AAPMCLOG_SUCCESS => "ERR::AAPMCLOG_SUCCESS",
ERR::ERR_MODIFYFAIL => "ERR::ERR_MODIFYFAIL",
ERR::ERR_UNEXPECTED => "ERR::ERR_UNEXPECTED",
ERR::ERR_MODIFYDUPLICATED => "ERR::ERR_MODIFYDUPLICATED",
);
print "[CkSysDrv] Read common configurations...\n" if ($DebugPrint &1);
#---------------------------------------------------
# Read common variables
#---------------------------------------------------
# macth int cksysdrv_enabled = 0 ;
if ($reading =~ /int\s+cksysdrv_enabled\s*=\s*(.*);/)
{
$cksysdrv_enabled = `perl -e "print ($1)" 2>&1`;
if ($cksysdrv_enabled == 0)
{
print "[ckSysDrv] ckSysDrv is disabled!";
exit(0);
}
}
# macth int fs_auto_config_support = 0 ;
if ($reading =~ /int\s+fs_auto_config_support\s*=\s*(.*);/)
{
$fs_auto_config_support = `perl -e "print ($1)" 2>&1`;
if ($fs_auto_config_support == 0)
{
print "[ckSysDrv] Auto adjust is disabled!\n";
}
if ($#ARGV < 6)
{
$fs_auto_config_support = 0;
}
print "[ckSysDrv] \$fs_auto_config_support = $fs_auto_config_support\n";
}
# macth int system_drive_location = 0 ;
if ($reading =~ /int\s+system_drive_location\s*=\s*(.*);/)
{
$system_drive_location = `perl -e "print ($1)" 2>&1`;
if ($system_drive_location == $ON_NOR)
{
print("[Input] System Drive Type = NOR\n")if ($DebugPrint &1);
$DEV_PREFIX = "NOR_BOOTING_NOR_";
$DEV_TYPE = "NOR";
}
elsif ($system_drive_location == $ON_NAND)
{
print("[Input] System Drive Type = NAND\n")if ($DebugPrint &1);
$DEV_PREFIX = "NAND_BOOTING_NAND_";
$DEV_TYPE = "NAND";
}
elsif ($system_drive_location == $ON_EMMC)
{
print("[Input] System Drive Type = EMMC\n")if ($DebugPrint &1);
$DEV_PREFIX = "EMMC_BOOTING_UP_";
$DEV_TYPE = "EMMC";
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "System drive location is unrecoginzed!", __FILE__, __LINE__);
}
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "System drive location is unrecoginzed!", __FILE__, __LINE__);
}
#match APP_STORAGE_IN_SYS_DRV
if ($reading =~ /int\s+app_storage_in_sys_drv\s*=\s*(.*);/)
{
$app_storage_in_sys_drv = `perl -e "print ($1)" 2>&1`;
printf("\t[Input] APP_STORAGE_IN_SYS_DRV: $app_storage_in_sys_drv\n") if ($DebugPrint &1);
}
if ($system_drive_location == $ON_NOR || $system_drive_location == $ON_NAND)
{
# macth int flash_base_address = 0x00E00000 ;
if ($reading =~ /int\s+flash_base_address\s*=\s*(.*);/)
{
$flash_base_address = `perl -e "print ($1)" 2>&1`;
$original_base_address = $flash_base_address;
printf("[Input] %sFS_BASE_ADDRESS = 0x%08X\n", $DEV_PREFIX, $flash_base_address)if ($DebugPrint &1);
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "FS base address is NOT found!", __FILE__, __LINE__);
}
# macth int allocated_fat_space = 0x00200000 ;
if ($reading =~ /int\s+allocated_fat_space\s*=\s*(.*);/)
{
$allocated_fat_space = `perl -e "print ($1)" 2>&1`;
$original_fat_space = $allocated_fat_space;
printf("[Input] %sFS_SIZE = 0x%08X\n", $DEV_PREFIX, $allocated_fat_space)if ($DebugPrint &1);
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "FS total size is NOT found!", __FILE__, __LINE__);
}
# macth int partition_sectors = 0 ;
if ($reading =~ /int\s+partition_sectors\s*=\s*(.*);/)
{
$first_partition_sectors = `perl -e "print ($1)" 2>&1`;
$original_first_partition_sectors = $first_partition_sectors;
$first_partition_size = $first_partition_sectors * 512;
printf("[Input] %sFS_FIRST_DRIVE_SECTORS = %d sectors(0x%08X bytes)\n", $DEV_PREFIX, $first_partition_sectors, $first_partition_size)if ($DebugPrint &1);
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "The first drive size is NOT found!", __FILE__, __LINE__);
}
}
elsif ($system_drive_location == $ON_EMMC) # EMMC booting
{
# macth int system_drive_size = 0 ;
if ($reading =~ /int\s+system_drive_size\s*=\s*(.*);/)
{
$system_drive_sectors = `perl -e "print ($1)" 2>&1`;
$system_drive_size = $system_drive_sectors * 512;
printf("[Input] %sFS_SIZE = %d sectors(0x%08X bytes)\n", $DEV_PREFIX, $system_drive_sectors, $allocated_fat_space)if ($DebugPrint &1);
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "[EMMC Booting] System drive size is NOT found!", __FILE__, __LINE__);
}
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "Unrecognizable device type", __FILE__, __LINE__);
}
print "\n[$DEV_TYPE] Read device specific configurations \n" if ($DebugPrint &1);
if ($system_drive_location == $ON_NAND) # System drive on NAND flash
{
#---------------------------------------------------
# NAND flash
#---------------------------------------------------
#print "(NAND)...\n" if ($DebugPrint &1);
# macth int nand_fdm_version = 0;
if ($reading =~ /int\s+nand_fdm_version\s*=\s*(.*);/)
{
$nand_fdm_version = `perl -e "print ($1)" 2>&1`; # 4 or 5
printf("\tFDM version: %d\n", $nand_fdm_version) if ($DebugPrint &1);
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "NAND FDM version is NOT found!", __FILE__, __LINE__);
}
if ($nand_fdm_version != 4 && $nand_fdm_version != 5)
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "Unsupported NAND FDM version!", __FILE__, __LINE__);
}
# macth int nand_block_size = 0;
if ($reading =~ /int\s+nand_block_size\s*=\s*(.*);/)
{
$nand_block_size = `perl -e "print ($1)" 2>&1`; # (KB)
printf("[CkSysDrv:NAND] Block size: %d (KB)\n", $nand_block_size) if ($DebugPrint &1);
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "NAND block size is NOT found!", __FILE__, __LINE__);
}
}
elsif ($system_drive_location == $ON_NOR) # System drive on NOR flash
{
#------------------------------------------------------------
# NOR flash
#------------------------------------------------------------
#print "(NOR)...\n";
# macth int fs_low_cost_support = 0 ;
if ($reading =~ /int\s+fs_low_cost_support\s*=\s*(.*);/)
{
$fs_low_cost_support = `perl -e "print ($1)" 2>&1`;
printf("\tUltra-low-cost support: %d\n", $fs_low_cost_support) if ($DebugPrint &1);
}
else
{
warn "[CkSysDrv:NOR] Ultra-low-cost indication is NOT found!";
undef $fs_low_cost_support;
}
# macth int nvram_custom_cfg_max_record_size = 4 ;
if ($reading =~ /int\s+nvram_custom_cfg_max_record_sector_num\s*=\s*(.*);/)
{
$nvram_custom_cfg_max_record_sector_num = `perl -e "print ($1)" 2>&1`;
printf("\tNVRAM maximum record size: %d\n", $nvram_custom_cfg_max_record_sector_num) if ($DebugPrint &1);
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED,
"NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM is NOT defined! It should be defined in custom\\common\\custom_nvram_config.h", __FILE__, __LINE__);
}
# match {float,int} nor_reserved_blocks = {1.5,5} ;
if ($reading =~ /int\s+nor_reserved_blocks\s*=\s*(.*);/)
{
$nor_reserved_blocks = `perl -e "print ($1)" 2>&1`;
printf("\tNOR FDM reserved blocks: %d\n", $nor_reserved_blocks) if ($DebugPrint &1);
}
elsif ($reading =~ /float\s+nor_reserved_blocks\s*=\s*(.*);/)
{
$nor_reserved_blocks = `perl -e "print ($1)" 2>&1`;
printf("\tNOR FDM reserved blocks: %.2f\n", $nor_reserved_blocks) if ($DebugPrint &1);
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "RESERVED BLOCKS is NOT found!", __FILE__, __LINE__);
}
# match int nor_single_bank_support = {1,0} ;
if ($reading =~ /int\s+nor_single_bank_support\s*=\s*(.*);/)
{
$nor_single_bank_support = `perl -e "print ($1)" 2>&1`;
}
# match int nor_sector_size = 512 ;
if ($reading =~ /int\s+nor_sector_size\s*=\s*(.*);/)
{
$nor_sector_size = `perl -e "print ($1)" 2>&1`;
printf("\tSector size: %d (Bytes)\n", $nor_sector_size) if ($DebugPrint &1);
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "SECTOR SIZE is NOT found!\n", __FILE__, __LINE__);
}
# macth FlashRegionInfo RegionInfo[] =
# {
# {0x20000, 16},
# EndRegionInfo
# };
if ($reading =~ /\s+RegionInfo\s*?\[\s*?\]\s*?=\s*?\{([\w\W]+?)\s*?\{0, 0\}\s*?\}\s*?;/)
{
$nor_regions = $1;
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "RegionInfo is NOT found!\n", __FILE__, __LINE__);
}
# match {0x20000, 16},
while ($nor_regions =~ /\{\s*(0x[\dA-Fa-f]+)\s*,\s*(\d+)\s*\}\s*,/)
{
my $sectors_per_block;
$nor_regions = $';
if ($nor_sector_size == 512)
{
$blockheader_overhead = 512;
$sectors_per_block = (hex($1) - $blockheader_overhead) / 512;
while ((($sectors_per_block + 1) * 4) > $blockheader_overhead)
{
$blockheader_overhead += 512;
$sectors_per_block--;
}
printf("\t\t[i]sectors_per_block = $sectors_per_block\n")if ($DebugPrint & 2);
}
elsif ($nor_sector_size == 1024)
{
$blockheader_overhead = 2048;
printf("\t\t[i]sectors_per_block = $sectors_per_block\n")if ($DebugPrint & 2);
}
$alignment = hex($1);
printf("\t\t[i]alignment = $alignment\n")if ($DebugPrint & 2);
$nor_max_blk_size = hex($1) - $blockheader_overhead if ($nor_max_blk_size < hex($1) - $blockheader_overhead);
printf("\t\t[i]nor_max_blk_size = $nor_max_blk_size\n")if ($DebugPrint & 2);
$blockheader_overhead_total = $blockheader_overhead * $2;
printf("\t\t[i]blockheader_overhead = $blockheader_overhead\n")if ($DebugPrint & 2);
}
}
if ($fs_auto_config_support == 1)
{
# match code_boundary_addr
printf ("Parsing $LINK_INFO\n") if ($DebugPrint &1);
open(LINK_INFO, "<$LINK_INFO") or warn "cannot open LINK_INFO: $LINK_INFO\n";
while (<LINK_INFO>)
{
printf("\t\t[i]%s\n", $_) if ($DebugPrint &1);
if ($system_drive_location == $ON_NOR)
{
#multi-bank, we can't adjust because FS addr. must align bank.
if ($nor_single_bank_support == 0)
{
cksysdrv_die(ERR::CANNOT_ADJUST, "Can't adjust FS base address because of multibank! Please consider turning on ENHANCED_SINGLE_BANK_NOR_FLASH_SUPPORT\n", __FILE__, __LINE__);
}
#this is temp solution, because don't know how big is code region when multi-bin
# release all freespace once the link error doesn't include key word: EXTSRAM, INTSRAM, CACHED and PAGE_TABLE
if (/L6220E:\s*Load\s*region\s*(.*)\s*size/)
{
printf("Link error: Load region = $1\n")if ($DebugPrint &1);
if ($1 =~ /(EXTSRAM|INTSRAM|CACHED|PAGE_TABLE)/)
{
printf("\tFalse alarm\n")if ($DebugPrint &1);
}
else
{
$code_boundary_addr = $release_all_free; #free all free space to code region
printf("\tRelease all free space\n")if ($DebugPrint &1);
}
}
# correct soultion is to calc all shortage,
# e.g. Error: L6220E: Load region ROM size (54932988 bytes) exceeds limit (1048576 bytes).
# if(/L6220E:\s*Load\s*region\s*ROM\s*size\s*\((.*)\s*bytes\)\s+exceeds\s+limit/)
# {
# $code_boundary_addr = $1;
# }
}
elsif ($system_drive_location == $ON_NAND || $system_drive_location == $ON_EMMC)
{
#match Error: BIN (413.52 blocks) and FAT (400 blocks) on NAND Flash overlap risk were detected.
if(/Error:\s*BIN\s*\((.*)\s*blocks\)\s*and\s*FAT\s*\((.*)\s*blocks\)/)
{
$code_boundary_addr = ($1 + 1) * $nand_block_size * 1024;
printf("Link error: Load region = $1 blocks\n")if ($DebugPrint &1);
}
if (/BIN\s*size\s*=\((.*)\s*blocks\)\s*on\s*NAND\s*Flash/)
{
$code_boundary_addr = $1;
printf("Load region = $1 blocks\n")if ($DebugPrint &1);
}
}
}
close LINK_INFO;
my $i = 0;
for (; $i < 10 ; $i++)
{
my $err_level_1 = calc_func();
print "\n\n[ckSysdrv result] $error_code{$err_level_1}($err_level_1)\n";
if ($err_level_1 == ERR::NO_MODIFY)
{
my $err_level_2 = adjust_func();
print "\n\n[AAPMC result] $error_code{$err_level_2}($err_level_2)\n";
exit $err_level_2;
}
elsif ($err_level_1 == ERR::MODIFY_SUCCESS)
{
print "\n\n[Retrying...]\n";
}
else
{
exit $err_level_1;
}
}
if ($i == 10)
{
if ($code_shortage_size > 0)
{
printf("Error: Shortage of code region (bytes, sectors) = (0x%08X, %d)\n", $code_shortage_size, $code_shortage_size/512);
}
elsif ($diff >= 0)
{
printf("Error: Shortage of FAT region: %d clusters (%d Sectors = %.1f KB = %.2f MB)\n", $diff, $diff * ($cluster_size / 512), $diff * $cluster_size / 1024, $diff * $cluster_size / (1024 * 1024));
}
cksysdrv_die(ERR::CANNOT_ADJUST, "Can't find an available setting. Check ckSysDrv.log for detail!\n", __FILE__, __LINE__);
}
}
else
{
calc_func();
if ($code_shortage_size > 0)
{
printf("Error: Shortage of code region (bytes, sectors) = (0x%08X, %d)\n", $code_shortage_size, $code_shortage_size/512);
exit ERR::ERR_UNEXPECTED;
}
elsif ($diff < 0)
{
printf("Error: Shortage of FAT region: %d clusters (%d Sectors = %.1f KB = %.2f MB)\n", -1*$diff, -1*$diff * ($cluster_size / 512), 1*$diff * $cluster_size / 1024, 1*$diff * $cluster_size / (1024 * 1024));
exit ERR::ERR_UNEXPECTED;
}
cksysdrv_die(ERR::NO_MODIFY, "Auto config is OFF this time!\n", __FILE__, __LINE__);
}
#---------------------------------------------------------
# Read device specific variables and calculate free space
#---------------------------------------------------------
sub calc_func
{
if ($system_drive_location == $ON_NAND) # System drive on NAND flash
{
print "[CkSysDrv:NAND] Calculate free space...\n" if ($DebugPrint &1);
if ($nand_block_size != 0)
{
if ($nand_fdm_version == 4)
{
#----------------------------------------------------------
# 12 : Reserved blocks in each region.
# 5 : Max possible bad blocks number in each region. (2%)
# Log_Block_Number : Number of log blocks. In 2KB NAND, the value is 3. In 528B page size NAND, the value is 6.
# Block_Size : 128KB or 16KB.
#----------------------------------------------------------
printf("allocated_fat_space = %d, nand_block_size = %d\n", $allocated_fat_space, $nand_block_size) if ($DebugPrint & 1);
$fat_nand_block_num = $allocated_fat_space / ($nand_block_size * 1024);
$fat_nand_region_num = ceil($fat_nand_block_num / 256);
if ($nand_block_size == 128)
{
$nand_log_block_num = 3;
}
elsif ($nand_block_size == 16)
{
$nand_log_block_num = 6;
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "Unsupported NAND block size!\n", __FILE__, __LINE__);
}
$free_space = ($fat_nand_block_num - (($fat_nand_region_num) * (12 + 5)) - ($nand_log_block_num)) * ($nand_block_size * 1024);
}
else # NAND FDM5
{
#----------------------------------------------------------
# Block_Size : 128KB or 16KB.
# 40 : Reserved blocks in each region (1024 blocks).
#----------------------------------------------------------
printf("\t\t[i]allocated_fat_space = %d, nand_block_size = %d\n", $allocated_fat_space, $nand_block_size) if ($DebugPrint & 1);
$fat_nand_block_num = $allocated_fat_space / ($nand_block_size * 1024);
$fat_nand_region_num = ceil($fat_nand_block_num / 1024);
printf("\t\t[i]nand_block_num = %d, nand_region_num = %d, nand_block_size = %d\n", $fat_nand_block_num, $fat_nand_region_num, $nand_block_size) if ($DebugPrint & 1);
$free_space = ($fat_nand_block_num - (($fat_nand_region_num) * 40)) * ($nand_block_size * 1024);
printf("\t\t[i]first_partition_size = $first_partition_size, first_partition_sectors = $first_partition_sectors\n") if ($DebugPrint & 1);
printf("\tBlock Number: %d\n", $fat_nand_block_num) if ($DebugPrint &1);
printf("\tRegion Number: %d\n", $fat_nand_region_num) if ($DebugPrint &1);
printf("\tFree Space: %d B = %d KB = %d MB\n", $free_space, $free_space / 1024, $free_space / (1024 * 1024)) if ($DebugPrint &1);
}
}
else # we have no NAND flash geometry information (before 09A), use 2KB page size to do more strict checking.
{
if ($nand_fdm_version == 4)
{
#----------------------------------------------------------
# 12 : Reserved blocks in each region.
# 5 : Max possible bad blocks number in each region. (2%)
# 3 : Number of log blocks. In 2KB NAND, 3 log blocks.
#----------------------------------------------------------
$fat_nand_block_num = $allocated_fat_space / (128 * 1024);
$fat_nand_region_num = ceil($fat_nand_block_num / 256);
$free_space = ($fat_nand_block_num - (($fat_nand_region_num) * (12 + 5)) - 3) * (128 * 1024);
}
else # NAND FDM5
{
#----------------------------------------------------------
# 40 : Reserved blocks in each region.
#----------------------------------------------------------
$fat_nand_block_num = $allocated_fat_space / (128 * 1024);
$fat_nand_region_num = ceil($fat_nand_block_num / 1024);
$free_space = ($fat_nand_block_num - (($fat_nand_region_num) * 40)) * (128 * 1024);
}
}
# Calculate system drive free space
$free_space = $free_space - $first_partition_size;
$alignment = ($nand_block_size * 1024);
printf("first_partition_size = $first_partition_size, first_partition_sectors = $first_partition_sectors\n") if ($DebugPrint & 1);
printf("[CkSysDrv:NAND] Block Number: %d\n", $fat_nand_block_num) if ($DebugPrint &1);
printf("[CkSysDrv:NAND] Region Number: %d\n", $fat_nand_region_num) if ($DebugPrint &1);
printf("[CkSysDrv:NAND] Free Space: %d B = %d KB = %d MB)\n", $free_space, $free_space / 1024, $free_space / (1024 * 1024)) if ($DebugPrint &1);
}
elsif ($system_drive_location == $ON_NOR) # System drive on NOR flash
{
print "[$DEV_TYPE] Calculate free space...\n" if ($DebugPrint &1);
printf("\t\t[i]nor_sector_size = $nor_sector_size\n")if ($DebugPrint & 2);
printf("\t\t[i]nvram_custom_cfg_max_record_sector_num = $nvram_custom_cfg_max_record_sector_num\n")if ($DebugPrint & 2);
$nor_protection_mode_reserved_space = ($nvram_custom_cfg_max_record_sector_num * 2 + 1) * $nor_sector_size;
printf("\t\t[i]nor_protection_mode_reserved_space = $nor_protection_mode_reserved_space\n")if ($DebugPrint & 2);
$nor_extra_reserved_space = 4 * $nor_sector_size if ($nor_reserved_blocks == $nor_min_reserved_blocks);
printf("\t\t[i]nor_min_reserved_blocks = $nor_min_reserved_blocks\n")if ($DebugPrint & 2);
printf("\t\t[i]nor_reserved_blocks = $nor_reserved_blocks\n")if ($DebugPrint & 2);
printf("\t\t[i]nor_extra_reserved_space = $nor_extra_reserved_space\n")if ($DebugPrint & 2);
$nor_extra_reserved_space_for_power_loss = 6 * $nor_sector_size if ($nor_sector_size == 512);
printf("\t\t[i]nor_extra_reserved_space_for_power_loss = $nor_extra_reserved_space_for_power_loss\n")if ($DebugPrint & 2);
$blockheader_overhead_total = ceil($allocated_fat_space/($nor_max_blk_size + $blockheader_overhead)) * $blockheader_overhead;
printf("\t\t[i]blockheader_overhead_total = $blockheader_overhead_total\n")if ($DebugPrint & 2);
printf("\t\t[i]blocks = %d\n", ceil($allocated_fat_space/$nor_max_blk_size))if ($DebugPrint & 2);
$nor_drive_overhead = $blockheader_overhead_total + ($nor_reserved_blocks * $nor_max_blk_size + $nor_protection_mode_reserved_space + $nor_extra_reserved_space + $nor_extra_reserved_space_for_power_loss);
printf("\t\t[i]nor_drive_overhead = $nor_drive_overhead\n")if ($DebugPrint & 2);
$free_space = $allocated_fat_space - $first_partition_size - $nor_drive_overhead; # in Byte
printf("\t\t[i]free_space = $free_space\n")if ($DebugPrint & 2);
}
elsif ($system_drive_location == $ON_EMMC) # System drive on EMMC
{
$allocated_fat_space = $free_space = $system_drive_size;
$alignment = 1;
}
else
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "Unsupported system drive location!\n", __FILE__, __LINE__);
}
print "[CkSysDrv] Calculate FAT type and cluster size...\n" if ($DebugPrint &1);
$cluster_size = -1; # in Byte
my $fat_type = 12;
if ($free_space == -1)
{
# free space is not available
$cluster_size = -2;
warn "[CkSysDrv] Free space is not available!";
}
elsif ($free_space < 1024 * 1024)
{
$cluster_size = 512;
}
elsif ($free_space < 4096 * 1024)
{
$cluster_size = 1024;
}
elsif ($free_space < 8192 * 1024)
{
$cluster_size = 2048;
}
elsif ($free_space < 16384 * 1024)
{
$cluster_size = 4096;
}
elsif ($free_space < 32 * 1024 * 1024)
{
$cluster_size = 1024;
$fat_type = 16;
}
elsif ($free_space < 128 * 1024 * 1024)
{
$cluster_size = 2048;
$fat_type = 16;
}
elsif ($free_space < 256 * 1024 * 1024)
{
$cluster_size = 4096;
$fat_type = 16;
}
elsif ($free_space < 512 * 1024 * 1024)
{
$cluster_size = 8192;
$fat_type = 16;
}
else
{
# when free space >= 512MB, no need to determine system drive free space;
# $cluster_size will be set as -1
warn "[CkSysDrv] System Drive >= 512MB , such configuration not supported by FileSystem in default";
}
printf("[CkSysDrv] FAT type: FAT%d\n", $fat_type) if ($DebugPrint &1);
printf("[CkSysDrv] Cluster size: %d (Bytes)\n", $cluster_size) if ($DebugPrint &1);
print "[CkSysDrv] Parse FS quota configurations...\n" if ($DebugPrint &1);
#****************************************************************************
# Parse ~fs_quota_usage.log to determine folder size
#****************************************************************************
# my $folder =
# {
# FOLDER => $folder_name,
# COUNT => $count,
# UNIT => $unit_byte,
# SIZE => $size_in_byte
# }
my @folder_size = ();
open(FS_STAT, "<$FS_STAT") or cksysdrv_die(ERR::ERR_UNEXPECTED, "cannot open FS_STAT: $FS_STAT\n\n", __FILE__, __LINE__);
$/ = $backup;
while (<FS_STAT>)
{
# match {Z:\@USER\, 0, 83968, 0xf1f2f3f4 , 0x1 },
if (/\{\s*(Z.+\\)\s*,[^,]+,\s*(\d+)\s*,[^,]+,\s*(0x[\dA-Fa-f]+)\s*\}\s*,/i)
{
my %this_folder = ();
$this_folder{FOLDER} = $1;
$this_folder{COUNT} = $2;
$this_folder{UNIT} = $3;
$this_folder{SIZE} = ($this_folder{UNIT} eq '0x1') ? ($this_folder{COUNT}) : ($this_folder{COUNT} * $cluster_size);
push @folder_size, \%this_folder;
}
}
close FS_STAT;
foreach my $folder (@folder_size)
{
printf("%-20s %10s\n", $folder->{FOLDER}, $folder->{SIZE}) if ($DebugPrint &4);
}
print "[CkSysDrv] Parse NVRAM configurations...\n" if ($DebugPrint &1);
#****************************************************************************
# Parse ~nvram_lid_size.log to get application's nvram reserved size info.
#****************************************************************************
my @app_rev_size = ();
# my $app =
# {
# APPLICATION => $app_name,
# SIZE => $size_in_byte # unit_size * record_num
# }
# For NVRAM-PSEUDO-MERGE usage.
my %this_app = ();
$this_app{APPLICATION} = "Package file size";
$this_app{SIZE} = "unknown";
push @app_rev_size, \%this_app;
my %this_app = ();
$this_app{APPLICATION} = "Info file A";
$this_app{SIZE} = "unknown";
push @app_rev_size, \%this_app;
my %this_app = ();
$this_app{APPLICATION} = "Info file B";
$this_app{SIZE} = "unknown";
push @app_rev_size, \%this_app;
my %this_app = ();
$this_app{APPLICATION} = "Extra size";
$this_app{SIZE} = "unknown";
push @app_rev_size, \%this_app;
foreach my $app (@app_rev_size)
{
printf("%-40s %10s\n", $app->{APPLICATION}, $app->{SIZE}) if ($DebugPrint & 1);
$cluster_multiple{$app->{APPLICATION}} = 1;
}
print("Start parse NVRAM LID\n") if ($DebugPrint &1);
open(NVRAM_STAT, "<$NVRAM_STAT") or cksysdrv_die(ERR::ERR_UNEXPECTED, "Cannot open NVRAM_STAT: $NVRAM_STAT\n\n", __FILE__, __LINE__);
my %app_size = ();
$/ = $backup;
while (<NVRAM_STAT>)
{
$_ =~ s/\bCUSTPACK\b//;
if (/(\d+)\s*(\d+)\s*(\w.+\w)/)
{
if (!defined($cluster_multiple{$3}))
{
my %this_app = ();
$this_app{APPLICATION} = $3;
$this_app{SIZE} = $2;
$cluster_multiple{$3} = 1;
print "push: " if ($DebugPrint &4);
push @app_rev_size, \%this_app;
}
if (defined $app_size{$3})
{
cksysdrv_die(ERR::ERR_UNEXPECTED, "$3 has different sizes $app_size{$3} vs. $2!\n", __FILE__, __LINE__) unless ($app_size{$3} == $2);
$app_size{$3} += $app_size{$3};
$cluster_multiple{$3} += 1;
}
else
{
$app_size{$3} = $2;
print "$app_size{$3} $3\n" if ($DebugPrint &4);
}
}
}
close NVRAM_STAT;
while ((my $key, my $value) = each %app_size)
{
# print "$key $value\n" if ($DebugPrint &1);
}
foreach my $app (@app_rev_size)
{
if ( ($NVRAM_PSEUDO_MERGE =~ /^ON|TRUE$/)
&& (!exists $app_size{$app->{APPLICATION}}))
{
$app_size{$app->{APPLICATION}} = 0;
}
if ($app->{SIZE} ne 'unknown')
{
if ($cluster_multiple{$app->{APPLICATION}} eq "1")
{
if ($app_size{$app->{APPLICATION}})
{
warn "$app->{APPLICATION} has different sizes $app->{SIZE} vs. $app_size{$app->{APPLICATION}}!" unless ($app->{SIZE} == $app_size{$app->{APPLICATION}});
}
}
$app->{SIZE} = $app_size{$app->{APPLICATION}};
}
else
{
$app->{SIZE} = $app_size{$app->{APPLICATION}};
}
printf("%-40s %10s\n", $app->{APPLICATION}, $app->{SIZE}) if ($DebugPrint &4);
}
print "[CkSysDrv] Parse file system management overhead...\n" if ($DebugPrint &1);
#****************************************************************************
# Determine FAT overhead
#****************************************************************************
# Calculate the freespace by removing MBR & PBR & FAT & Root DIR space.
my $fat_overhead_cluster;
my $tmp_free_space = $free_space;
# MBR
$tmp_free_space -= 512;
# PBR
$tmp_free_space -= 512;
# FAT
if ($fat_type == 12)
{
# FAT-12
# DIR
if ($fs_low_cost_support == 1)
{
$tmp_free_space -= (16 * 32); # 1
}
else
{
$tmp_free_space -= (128 * 32); # 8
}
# FAT Table
my $fat_size = 0;
if ($cluster_size > 0)
{
while (($fat_size * 2 / 3) * $cluster_size < $tmp_free_space)
{
$fat_size += 512;
$tmp_free_space -= 512;
}
}
}
else
{
# FAT-16
# DIR
if ($fs_low_cost_support == 1)
{
$tmp_free_space -= (16 * 32); # 1
}
else
{
$tmp_free_space -= (512 * 32); # 32
}
# FAT Table
my $fat_size = 0;
if ($cluster_size > 0)
{
while (($fat_size / 2) * $cluster_size < $tmp_free_space)
{
$fat_size += 512;
$tmp_free_space -= 512;
}
}
}
# Example:
#Z:\@WAP\
#Z:\@DRM\
#Z:\NVRAM\NVD_DATA\NVRAM_EF_PHB_LID
# \NVRAM_EF_SMS_LID
# dir entry of level-1 (in cluster unit) = 2 (@WAP, @DRM)
# dir entry of level-2 (in direntry cnt) = 2 + 1 ("." , ".." , NVD_DATA) at Z:\NVRAM
# dir entry of level-3 (in direntry cnt) = 2 + 2 ("." , ".." , NVRAM_EF_PHB_LID, NVRAM_EF_SMS_LID) at Z:\NVRAM\NVD_DATA
my $fat_overhead_cluster;
if ($cluster_size > 0)
{
# level-1 directory entries + level-2 directory entries + level-3 directory entries
$fat_overhead_cluster = ($#folder_size + 1) + ceil((2 + 1) * 32 / $cluster_size) + ceil((2 + ($#app_rev_size + 1)) * 32 / $cluster_size);
}
print "[CkSysDrv] Print result...\n" if ($DebugPrint &1);
print("===========================================================\n");
#****************************************************************************
# Print out the result
#****************************************************************************
#1.
# die "Free space is greater than 16MB!";
#print "SYSTEM_DRIVE_ON_NAND = $SYSTEM_DRIVE_ON_NAND\n";
#print "FAT_BASE_ADDRESS = $flash_base_address (".hex($flash_base_address).")\n";
print(" Byte Cluster\n");
print("===========================================================\n");
if ($system_drive_location == $ON_NOR || $system_drive_location == $ON_NAND)
{
printf("FS Total Size %36s %7s\n", $allocated_fat_space, $allocated_fat_space/$cluster_size);
printf("FS Public(First) Drive Size %23s %7s\n", $first_partition_size, $first_partition_size/$cluster_size);
printf("FS Overhead for (MBR + PBR + Root Dir) %12s %7s\n", $free_space - $tmp_free_space, ($free_space - $tmp_free_space)/$cluster_size);
if ($system_drive_location == $ON_NOR)
{
printf("FDM Overhead (NOR) %32s %7s\n", $nor_drive_overhead, $nor_drive_overhead/$cluster_size);
}
elsif ($system_drive_location == $ON_NAND)
{
printf("FDM Overhead (NAND) %31s %7s\n", ($fat_nand_region_num * 40) * ($nand_block_size * 1024), ($fat_nand_region_num * 40) * ($nand_block_size * 1024)/$cluster_size);
}
}
else #EMMC
{
printf("FS System Drive Size %29s \n", $free_space);
}
$free_space = $tmp_free_space;
my $free_space_cluster = floor($free_space / $cluster_size);
my $app_rev_total = 0;
my $app_rev_total_cluster = 0;
my $folder_total = 0;
my $folder_total_cluster = 0;
my $nv_overhead = 0;
my $nv_overhead_cluster = 0;
my $mini_public_drv_sectors = 0;
#CYLEN: need to calc real overhead of NVRAM
if ($NVRAM_PSEUDO_MERGE =~ /^ON|TRUE$/)
{
$nv_overhead = 10;
}
else
{
$nv_overhead = 15;
}
printf("NVRAM reserved folder overhead %20s %7s\n", $nv_overhead * $cluster_size, $nv_overhead);
if ($free_space_cluster >= $nv_overhead)
{
$free_space_cluster -= $nv_overhead;
}
else
{
$free_space_cluster = 0;
}
$nv_overhead = 0;
print("===========================================================\n");
if ($cluster_size > 0)
{
printf("Free Space for NVRAM and App's Folders %12s %7s\n\n", $free_space, $free_space_cluster);
print("-----------------------------------------------------------\n");
printf("FAT Type %38s \n", $fat_type);
printf("Cluster Size %38s 1\n", $cluster_size);
print("-----------------------------------------------------------\n");
printf("FAT Overhead for Sub Dir %26s %7s\n", $fat_overhead_cluster * $cluster_size, $fat_overhead_cluster);
print("-----------------------------------------------------------\n");
foreach my $app (@app_rev_size)
{
if ($app->{SIZE} ne "unknown")
{
printf("%-40s %10s %7s\n", $app->{APPLICATION}, $app->{SIZE}, ceil($app->{SIZE} / $cluster_multiple{$app->{APPLICATION}} / $cluster_size) * $cluster_multiple{$app->{APPLICATION}}) if ($DebugPrint == 0 || ($DebugPrint & 8) == 1);
$app_rev_total += $app->{SIZE};
$app_rev_total_cluster += ceil($app->{SIZE} / $cluster_multiple{$app->{APPLICATION}} / $cluster_size) * $cluster_multiple{$app->{APPLICATION}};
}
else
{
printf("%-40s %10s %7s\n", $app->{APPLICATION}, $app->{SIZE}, $app->{SIZE}) if ($DebugPrint == 0 || ($DebugPrint & 8) == 1);
}
}
for(keys %cluster_multiple)
{
delete $cluster_multiple{$_};
}
if (defined $app_size{'SW CHANGE LID LIST'})
{
printf("%-40s %10s %7s\n", "NVRAM_EXTRA_REPORT_FILES", $app_size{'SW CHANGE LID LIST'}, ceil($app_size{'SW CHANGE LID LIST'} / $cluster_size)) if ($DebugPrint == 0 || ($DebugPrint & 8) == 1);
$nv_overhead += $app_size{'SW CHANGE LID LIST'};
$nv_overhead_cluster += ceil($app_size{'SW CHANGE LID LIST'} / $cluster_size);
}
if (defined $app_size{'SW CHANGE LID DESCRIPTION'})
{
printf("%-40s %10s %7s\n", "NVRAM_EXTRA_REPORT_FILES", $app_size{'SW CHANGE LID DESCRIPTION'}, ceil($app_size{'SW CHANGE LID DESCRIPTION'} / $cluster_size)) if ($DebugPrint == 0 || ($DebugPrint & 8) == 1);
$nv_overhead += $app_size{'SW CHANGE LID DESCRIPTION'};
$nv_overhead_cluster += ceil($app_size{'SW CHANGE LID DESCRIPTION'} / $cluster_size);
}
printf("\nTOTAL %45s %7s\n", $app_rev_total + $nv_overhead, $app_rev_total_cluster + $nv_overhead_cluster);
print("-----------------------------------------------------------\n");
foreach my $folder (@folder_size)
{
if ($folder->{SIZE} ne "unknown")
{
printf("%-40s %10s %7s\n", $folder->{FOLDER}, $folder->{SIZE}, ceil($folder->{SIZE} / $cluster_size)) if ($DebugPrint == 0 || ($DebugPrint & 8) == 1);
$folder_total += $folder->{SIZE};
$folder_total_cluster += ceil($folder->{SIZE} / $cluster_size);
}
else
{
printf("%-40s %10s %7s\n", $folder->{FOLDER}, $folder->{SIZE}, $folder->{SIZE}) if ($DebugPrint == 0 || ($DebugPrint & 8) == 1);
}
}
printf("\nTOTAL %45s %7s\n", $folder_total, $folder_total_cluster);
print("===========================================================\n");
my $folder_and_app_clusters = $fat_overhead_cluster + $app_rev_total_cluster + $nv_overhead_cluster + $folder_total_cluster;
$diff = $free_space_cluster - $folder_and_app_clusters;
print("\nREPORT\n");
print("===========================================================\n");
printf("Cluster Size (Bytes) %38s\n", $cluster_size);
printf("Free Space (Clusters) %37s\n", $free_space_cluster);
printf("Folders and Applications Requirement (Clusters) %11s\n", $folder_and_app_clusters);
print("\n");
if ($system_drive_location == $ON_NAND)
{
$mini_public_drv_sectors = 400;
}
elsif ($system_drive_location == $ON_NOR)
{
$mini_public_drv_sectors = 25;
}
if ($diff >= 0)
{
my $diff_size = $diff * $cluster_size;
print("RESULT: PASS!\n");
printf("%d clusters are left (%.1f KB = %.2f MB)\n", $diff, $diff_size / 1024, $diff_size / (1024 * 1024));
if ($fs_auto_config_support == 0)
{
return ERR::NO_MODIFY;
}
#this is temp solution, because don't know how big is code region when multi-bin
if ($code_boundary_addr == $release_all_free)
{
$code_boundary_addr = $flash_base_address + $diff_size + $first_partition_size;
$code_shortage_size = $first_partition_size + $diff_size;
$short_block = floor($code_shortage_size/$alignment);
$short_block_size = $short_block * $alignment;
}
elsif ($code_boundary_addr > 0)
{
$code_shortage_size = $code_boundary_addr - $flash_base_address;
$short_block = floor($code_shortage_size/$alignment);
$short_block_size = $short_block * $alignment;
}
if ($code_shortage_size > 0)
{
printf("But Code & FAT overlap!\n");
printf("Code region still need 0x%08X bytes (%d sectors, %d blocks)\n", $code_shortage_size, $code_shortage_size/512, $short_block);
printf("\t\t[i]code_boundary_addr = 0x%08X(%d)\n", $code_boundary_addr, $code_boundary_addr) if ($DebugPrint & 2);
printf("\t\t[i]flash_base_address = 0x%08X(%d)\n", $flash_base_address, $flash_base_address) if ($DebugPrint & 2);
printf("\t\t[i]short_block_size = 0x%08X(%d)\n", $short_block_size, $short_block_size) if ($DebugPrint & 2);
printf("\t\t[i]first_partition_size = 0x%08X(%d)\n", $first_partition_size, $first_partition_size) if ($DebugPrint & 2);
printf("\t\t[i]diff = 0x%08X(%d)\n", $diff_size, $diff_size) if ($DebugPrint & 2);
if ($diff_size + $first_partition_size < $alignment) # free space less than one block --> fail
{
printf("FAT region has no block-aligned space to free!\n");
return ERR::CANNOT_ADJUST;
}
#this is temp solution, because don't know how big is code region when multi-bin
$flash_base_address += $short_block_size;
$allocated_fat_space -= $short_block_size;
printf("\t[Adjust] $DEV_PREFIX\FS_BASE_ADDRESS (bytes, sectors) = (0x%08X, %d)\n", $flash_base_address, $allocated_fat_space/512) if ($DebugPrint & 2);
printf("\t[Adjust] $DEV_PREFIX\FS_SIZE (bytes, sectors) = (0x%08X, %d)\n", $allocated_fat_space, $allocated_fat_space/512) if ($DebugPrint & 2);
if ($first_partition_size > 0)
{
if ($first_partition_size < $short_block_size )
{
if ($app_storage_in_sys_drv == 1)
{
$first_partition_size = 0;
}
else
{
if ($first_partition_size > $mini_public_drv_sectors * 1024)
{
$first_partition_size = $mini_public_drv_sectors * 1024;
}
else
{
;
}
}
}
else
{
if ($app_storage_in_sys_drv == 1)
{
$first_partition_size -= $short_block_size;
if ($first_partition_size < $mini_public_drv_sectors * 1024)
{
$first_partition_size = 0;
}
}
else
{
if ($first_partition_size - $short_block_size > $mini_public_drv_sectors * 1024)
{
$first_partition_size -= $short_block_size;
$short_block_size = 0;
}
else
{
$short_block_size -= ($first_partition_size - $mini_public_drv_sectors * 1024);
$first_partition_size = $mini_public_drv_sectors * 1024;
}
}
}
printf("\t[Adjust] $DEV_PREFIX\FIRST_DRIVE_SIZE (bytes, sectors) = (0x%08X, %d)\n", $first_partition_size, $first_partition_size/512) if ($DebugPrint & 2);
}
#this is temp solution, because don't know how big is code region when multi-bin
$code_boundary_addr = $flash_base_address;
$code_shortage_size = 0;
return ERR::MODIFY_SUCCESS;
}
return ERR::NO_MODIFY;
}
else
{
my $diff_size = $diff * $cluster_size * (-1);
my $free_flash_block_space = ceil(($first_partition_size + $free_space)/$alignment); #in Byte
my $diff_block = ceil($diff_size/$alignment);
my $diff_block_size = $diff_block * $alignment;
print("RESULT: FAIL!\n");
printf("FAT region still need 0x%08X bytes (%d sectors)\n", $diff_block_size, $diff_block_size/512);
warn "Free clusters are NOT enough. ";
#print("\nINSTRUCTION\n");
#print("===========================================================\n");
#print("Please help try following action items to solve this error. Suggested order is \n");
#print("\n");
#printf("1) Shrink FS First Drive Size to enlarge system drive size (Shrink at least %d sectors).\n", $diff * ($cluster_size / 512));
#print("2) Enlarge FS Region Size.\n");
#print("3) Disable some features to shrink quota requirement.\n");
#print("4) Replace flash device with another bigger one (Custom release projects only).\n");
print("\n");
if ($FEATURE_OVERLOAD ne "TRUE")
{
printf("Diff = %dbytes = %dclusters = %dblocks(%d bytes)\n", $diff_size, -1 * $diff, $diff_block, $alignment) if ($DebugPrint & 2);
printf("SYSDRV_OFFSET (bytes, sectors) = %d, %d\n", $first_partition_size, $first_partition_size/512) if ($DebugPrint & 2);
printf("Free space (free_flash_block_space): $free_flash_block_space blocks\n") if ($DebugPrint & 2);
if ($fs_auto_config_support == 1)
{
if ($system_drive_location == $ON_EMMC)
{
$allocated_fat_space = $system_drive_size = $allocated_fat_space + $diff_size;
printf("\t[Adjust] $DEV_PREFIX\FS_SIZE (bytes, sectors) = (0x%08X, %d)\n", $allocated_fat_space, $allocated_fat_space/512) if ($DebugPrint & 2);
}
else
{
if ($first_partition_size > 0) #inside FS, already block-aligned, don't need to calc with alignment
{
if ($first_partition_size < $diff_size )
{
if ($app_storage_in_sys_drv == 1)
{
$diff_size -= $first_partition_size;
$first_partition_size = 0;
}
else
{
if ($first_partition_size > $mini_public_drv_sectors * 1024)
{
$diff_size -= ($first_partition_size - $mini_public_drv_sectors * 1024);
$first_partition_size = $mini_public_drv_sectors * 1024;
}
else
{
;
}
}
}
else
{
if ($app_storage_in_sys_drv == 1)
{
$first_partition_size -= $diff_size;
if ($first_partition_size < $mini_public_drv_sectors * 1024)
{
$first_partition_size = 0;
}
$diff_size = 0;
}
else
{
if ($first_partition_size - $diff_size > $mini_public_drv_sectors * 1024)
{
$first_partition_size -= $diff_size;
$diff_size = 0;
}
else
{
$diff_size -= ($first_partition_size - $mini_public_drv_sectors * 1024);
$first_partition_size = $mini_public_drv_sectors * 1024;
}
}
}
}
printf("%04d Adjust SYSDRV_OFFSET (bytes, sectors) = (0x%08X, %d)\n", __LINE__, $first_partition_size, $first_partition_size/512) if ($DebugPrint & 2);
#out of FS, must consider alignment
$diff_block = ceil($diff_size/$alignment);
$diff_block_size = $diff_block * $alignment;
# if ($diff_block_size > ($free_flash_block_space * $alignment)) # free space less than one block --> fail
# {
# printf("FAT region has no block-aligned space to free!\n");
# return ERR::CANNOT_ADJUST;
# }
# else
{
$flash_base_address -= $diff_block_size;
$allocated_fat_space += $diff_block_size;
printf("%04d Adjust flash_base_address (bytes, sectors) = (0x%08X, %d)\n", __LINE__, $flash_base_address, $allocated_fat_space/512) if ($DebugPrint & 2);
printf("%04d Adjust allocated_fat_space (bytes, sectors) = (0x%08X, %d)\n", __LINE__, $allocated_fat_space, $allocated_fat_space/512) if ($DebugPrint & 2);
}
}
return ERR::MODIFY_SUCCESS;
}
}
return ERR::NO_MODIFY;
}
}
else
{
printf("Free Space for NVRAM and App's Folders %11s\n\n", $free_space);
print("-----------------------------------------------------------\n");
print("Cluster Size No need to be determined if Free space >= 512MB\n");
print("-----------------------------------------------------------\n");
print("FAT Overhead No need to be determined if Free space >= 512MB\n");
print("-----------------------------------------------------------\n");
foreach my $app (@app_rev_size)
{
printf("%-40s %10s\n", $app->{APPLICATION}, $app->{SIZE});
$app_rev_total += $app->{SIZE} if ($app->{SIZE} ne "unknown");
}
printf("\nTOTAL %45s\n", $app_rev_total);
print("-----------------------------------------------------------\n");
foreach my $folder (@folder_size)
{
printf("%-40s %10s\n", $folder->{FOLDER}, $folder->{SIZE});
$folder_total += $folder->{SIZE} if ($folder->{SIZE} ne "unknown");
}
printf("\nTOTAL %45s\n", $folder_total);
print("===========================================================\n");
print "\n\nFree space >= 512MB are enough for Folders and Applications.\n";
return ERR::NO_MODIFY;
}
}
sub adjust_func
{
my (%ChangeList, %OriginalList);
my $fat_space = sprintf("0x%08X", $allocated_fat_space);
my $base_addr = sprintf("0x%08X", $flash_base_address);
my $sysdrv_offset = sprintf("%d", $first_partition_size/512);
if ($DebugPrint & 4)
{
my $tmp_h_path = "$BOARD_FOLDER\\fs_layout.h";
open(tmp_h_path, "> $tmp_h_path") || cksysdrv_die(ERR::ERR_UNEXPECTED, "cannot open fs_layout.h: $tmp_h_path\n\n", __FILE__, __LINE__);
print tmp_h_path "/* Always generated by ckSysDrv automatically */\n";
print tmp_h_path "\n";
print tmp_h_path "#ifdef __CKSYSDRV_AUTO_ADJ__\n";
print tmp_h_path "\n";
printf(tmp_h_path "#ifdef %sFS_BASE_ADDRESS \n", $DEV_PREFIX);
printf(tmp_h_path "#undef %sFS_BASE_ADDRESS \n", $DEV_PREFIX);
printf(tmp_h_path "#define %sFS_BASE_ADDRESS $base_addr\n", $DEV_PREFIX);
print tmp_h_path "#endif\n";
print tmp_h_path "\n";
printf(tmp_h_path "#ifdef %sFS_SIZE\n", $DEV_PREFIX);
printf(tmp_h_path "#undef %sFS_SIZE\n", $DEV_PREFIX);
printf(tmp_h_path "#define %sFS_SIZE $fat_space\n", $DEV_PREFIX);
print tmp_h_path "#endif\n";
print tmp_h_path "\n";
printf(tmp_h_path "#ifdef %sFS_FIRST_DRIVE_SECTORS\n", $DEV_PREFIX);
printf(tmp_h_path "#undef %sFS_FIRST_DRIVE_SECTORS\n", $DEV_PREFIX);
printf(tmp_h_path "#define %sFS_FIRST_DRIVE_SECTORS %d\n", $DEV_PREFIX, $sysdrv_offset);
print tmp_h_path "#endif\n";
print tmp_h_path "\n";
print tmp_h_path "#endif /* __CKSYSDRV_AUTO_ADJ__ */\n";
close tmp_h_path;
}
if ($original_base_address != $flash_base_address)
{
$ChangeList{"$DEV_PREFIX\FS_BASE_ADDRESS"} = $base_addr;
$OriginalList{"$DEV_PREFIX\FS_BASE_ADDRESS"} = sprintf("0x%08X", $original_base_address);
}
if ($original_fat_space != $allocated_fat_space)
{
$ChangeList{"$DEV_PREFIX\FS_SIZE"} = $fat_space;
$OriginalList{"$DEV_PREFIX\FS_SIZE"} = sprintf("0x%08X", $original_fat_space);
}
if ($original_first_partition_sectors != $first_partition_size/512)
{
$ChangeList{"$DEV_PREFIX\FS_FIRST_DRIVE_SECTORS"} = $sysdrv_offset;
$OriginalList{"$DEV_PREFIX\FS_FIRST_DRIVE_SECTORS"} = sprintf("%d", $original_first_partition_sectors);
}
if (%ChangeList)
{
my $err;
open(LINK_INFO, "> $LINK_INFO") or warn "cannot open $LINK_INFO\n";
system("echo content of AAPMC.log:") if ($DebugPrint & 1);
system("if exist $AAPMCLOG (type $AAPMCLOG) else echo File not exist") if ($DebugPrint & 2);
if( ERR::AAPMCLOG_SUCCESS == &AAPMCLogParser::Open($AAPMCLOG))
{
my $report = "[Before Adjustment]\n";
while(my ($key, $value) = each(%OriginalList))
{
my $string = sprintf(" $key: $value\n");
$report = $report.$string;
}
$report .= "[AfterAdjustment]\n";
while(my ($key, $value) = each(%ChangeList))
{
my $string = sprintf(" $key: $value\n");
$report = $report.$string;
}
my $P4Info_ref = &AUTO_ADJUST::CreateP4InfoTemplate("",#OWNER,
"",#$PROJECT,
"Auto adjust FAT setting",
$report);
$err = &AAPMCLogParser::AddOneChangeRecord("$BOARD_FOLDER\\custom_MemoryDevice.h",
\%ChangeList, \%$P4Info_ref);
print "[AAPMC] return code: $error_code{$err}($err)\n";
if($err == ERR::ERR_MODIFYDUPLICATED)
{
printf(LINK_INFO "[AAPMC] can't modified more than twice\n");
}
elsif ($err == ERR::AAPMCLOG_SUCCESS)
{
printf(LINK_INFO "[AAPMC] add successfully!\n".$report);
}
else
{
printf(LINK_INFO "[AAPMC] unexcept error: $err\n");
}
&AAPMCLogParser::Close($AAPMCLOG);
}
else
{
printf(LINK_INFO "[AAPMC] load AAPMCLog failed\n");
}
close LINK_INFO;
system("echo content of CheckBinaryBlockUsage.log:") if ($DebugPrint & 1);
system("if exist .\\build\\$PROJECT\\log\\CheckBinaryBlockUsage.log (type .\\build\\$PROJECT\\log\\CheckBinaryBlockUsage.log) else echo File not exist") if ($DebugPrint & 2);
system("echo content of $LINK_INFO") if ($DebugPrint & 2);
system("type $LINK_INFO") if ($DebugPrint & 2);
return $err;
}
else
{
system("echo content of CheckBinaryBlockUsage.log") if ($DebugPrint & 1);
system("if exist .\\build\\$PROJECT\\log\\CheckBinaryBlockUsage.log (type .\\build\\$PROJECT\\log\\CheckBinaryBlockUsage.log) else echo File not exist") if ($DebugPrint & 2);
return ERR::NO_MODIFY
}
}
sub cksysdrv_die
{
my ($err, $error_msg, $file, $line_no) = @_;
my $final_error_msg = "[ckSysDrv]: $error_msg at $file line $line_no : ($error_code{$err})!\n";
print($final_error_msg);
if ($#ARGV > 5)
{
open(LINK_INFO, "> $LINK_INFO") or die "cannot open LINK_INFO: $LINK_INFO\n";
printf(LINK_INFO $final_error_msg);
close LINK_INFO;
}
exit $err;
}