-- -- Copyright (C) 2005 dahua Technologies, All Rights Reserved. -- 2006-4-25 15:54 Z:\wjj\ven\152\DAHUA\Install.lua -- 2006-9-21 modified by zhongjl for new partition -- -- Flash 块的大小为64K local flashSectorSize = 0x10000; local Installer = {}; Installer.TotalSize = 0; -- 总的要写到Flash中的数据大小 Installer.InProgressSize = 0; -- 用来在升级过程中控制进度 -- 通知上层应用程序升级的进度信息 -- params: -- 无 -- return: -- 无 function Installer:notify() self.InProgressSize = self.InProgressSize + flashSectorSize; local progress = self.InProgressSize / self.TotalSize * 100; if(progress > 100) then progress = 100; end; progress = tonumber(string.format("%d", progress)); -- 注意调用方式,不是self::callback,否则会导致回调出错 self.callback(0x01, progress); end -- 根据应用程序提供的信息判断是否可以升级 -- params: -- 无 -- return: -- 成功返回True, 失败返回False以及失败的原因 function Installer:preInstall() -- 这里我们需要考虑那些因数? -- 硬件版本号 ? -- 原有软件的版本号? -- local board = Global.Hardware.board; local hwproduct; local hwchannel; local hwversion; local hwfunction; print(string.format("Checking hardware information,board name:%s version:%s", board.name, board.version)); if((board.name ~= "DVRxx04HD-X" and board.name ~= "DVRxx04HF-X-E") or (board.version ~= "2.00")) then return false, "Invalid board"; end --升级程序直接从硬件中取值。意义如下 --hwproduct取值如下: 2 -- LB; 3 -- LBN; 4 -- LB_ATM; 5 -- GBE; 6 -- LK; 7 -- LS --hwproduct取值如下: 2 -- IPC4X5; 3 -- A6; 4 -- A8; 5 -- IPVM; --hwchannel取值如下: x -- x chans --hwfunction取值如下: 0 -- AUDIO; 1 -- MATRIX; 3 -- LOOP if(mtd.getinfo)then hwproduct,hwchannel,hwversion,hwfunction = mtd.getinfo(); print(string.format("Checking hardware id info: product = %x; channel = %x; version = %x; function = %x", hwproduct,hwchannel,hwversion,hwfunction)); if((hwproduct ~= 3) and (hwproduct ~= 4)) then print(string.format("product not match")); return false, "Invalid board"; end end -- 这里我们需要校验不同板本的板子程序是否可以通用, -- 如目前LB 1.22的与 LB 2.00的板子就不能通用 -- if(board.version ~= "1.22") then -- print(string.format("XXXXXXXXXXXX")); -- return false, "Invalid board version"; -- end local vendor = Global.Vendor; if(vendor.Name ~= 'General_N6'and vendor.Name ~= 'General') then return false, "Invalid vendor"; end return true; end -- 升级完成后的处理,如控制系统重启 -- params: -- 无 -- return: -- 无 function Installer:postInstall() end -- 升级Flash分区,对于不同的应用,升级的处理可能不一样 -- params : -- part : 表格,包含分区的起始位置以及结束位置 -- filename : 在升级包中的文件名 -- return : 无 function Installer:updatePart(part, filename) local myfile = self.ZipArchive:open(filename); local write_times = 0; -- 如果该文件打不开,则不需要对此部分进行升级 if(not myfile) then print(string.format("%s not exist", filename)); return ; end local addr = part.baseAddr; local endAddr= part.endAddr; local data; local fldata; local write_times1 = 0; print(string.format("Start Update : %s ", filename)); -- 跳过前面64字节的头,在新的升级程序版本中不需要对此进行校验 myfile:seek("set", 64); while(addr < endAddr) do fldata = mtd.read(addr,flashSectorSize); data = myfile:read(flashSectorSize); -- 读入一块Flash扇区大小的数据 -- if (fldata and data and (fldata ~= data)) then -- 当fldata为空的时候为老的程序,直接擦除 if(data) then if((not fldata) or (data and (fldata ~= data))) then mtd.erase(addr); mtd.write(addr, data); write_times = write_times+1; fldata = mtd.read(addr,flashSectorSize); if((not fldata) or (data and (fldata ~= data))) then mtd.erase(addr); mtd.write(addr, data); write_times1 = write_times1 + 1; end end self:notify(); addr = addr + flashSectorSize; else addr = endAddr; end end print(string.format("==========> Write Times : %s write_times1 : %s<==========", write_times, write_times1)); myfile:close(); end function Installer:InstallPlayer(filename) local myfile = self.ZipArchive:open(filename); -- 如果该文件打不开,则不需要对此部分进行升级 if(not myfile) then return ; end -- -- TODO: -- 读入自动播放器的内容,通过IDE接口写入到硬盘 -- end --对压缩包里的img文件进行校验,校验正确返回1,错误返回0 function Installer:crc32check( filename) local myfile = self.ZipArchive:open(filename); -- 如果该文件打不开(即无此文件),则不需要对此部分进行升级 if(not myfile) then print(string.format("==>Installer:crc32check not myfile %s , no need to check", filename)); return 1; end -- 如果应用程序无校验接口,则不需校验,直接返回成功,以兼容以前的应用程序 if(not mtd.check_init) then print(string.format("==>Installer:crc32check not mtd.check_init, no need to check") ); return 1 end if(not mtd.crc32)then print(string.format("==>Installer:crc32check not mtd.crc32, no need to check")); return 1 end local head = myfile:read(64);--读64个字节的头 local filesize = 0; local filecrc32 = 0; print(string.format("==>Installermtd.check_init")); filesize, filecrc32 = mtd.check_init(head);-- 初始化 print(string.format("==>Installer mtd.check_init over, filesize:%d filecrc:%x!", filesize, filecrc32)); local checksum = 0; local readlen =0; local data; -- 对数据部分计算校验和 while (readlen < filesize) do data = myfile:read(flashSectorSize); --print(string.format("Installer check crc32:%x ------%x!", checksum, readlen) ); if (filesize - readlen < flashSectorSize) then checksum = mtd.crc32(checksum, data, filesize - readlen) else checksum = mtd.crc32(checksum, data, flashSectorSize) end readlen = readlen + flashSectorSize; end if (checksum ~= filecrc32) then print(string.format("==>error: Installer check (%s)crc32 error:%x ------%x!", filename, checksum, filecrc32)); return 0; end print(string.format("==>correct: Installer check(%s) crc32 correct:%x ------%x!", filename, checksum, filecrc32)); return 1; end -- 在这里控制整个升级过程 -- params: -- 无 -- return: -- 成功返回True,失败返回Flase以及错误原因 function Installer:execute() --[[ 分区配置信息表,来自知识库 "Flash 分区规划" 0xa0000000 - 0xa0040000 256K armboot u-boot 0xa0060000 - 0xa0460000 4096K kernel + root romfs 0xa0460000 - 0xa0a60000 6144K application + modules user 0xa0a60000 - 0xa0c60000 1536K web web 0xa0c60000 - 0xa0e60000 2560K slave:romfs + kernel + pcidriver slave 0xa0e60000 - 0xa0e80000 128K custom custom 0xa0e80000 - 0xa0ec0000 256K logo logo 0xa0ec0000 - 0xa0f40000 1024K config 0xa0f40000 - 0xa1000000 1024K config1 ]] local flashPartions = { boot = { baseAddr = 0xa0000000 , endAddr = 0xa0040000 }, rootfs = { baseAddr = 0xa0080000 , endAddr = 0xa1780000 }, web = { baseAddr = 0xa1780000 , endAddr = 0xa1B00000 }, custom = { baseAddr = 0xa1B00000 , endAddr = 0xa1B80000 }, logo = { baseAddr = 0xa1B80000 , endAddr = 0xa1C40000 }, config = { baseAddr = 0xa1C40000 , endAddr = 0xa1D80000 }, config1 = { baseAddr = 0xa1D80000 , endAddr = 0xa2000000 }, } -- self.ZipArchive 这个变量由外部程序设置,如果没有设置程序不应该运行到这里 assert(self.ZipArchive); local zfile = self.ZipArchive; local ret, info = self:preInstall(); if(not ret) then return false, info; end -- 计算要升级的文件大小以及打印升级文件清单 local TotalSize = 0; print("==>Files in archive"); for file in zfile:files() do print(file.filename); TotalSize = TotalSize + file.uncompressed_size; end self.TotalSize = TotalSize; -- 总的文件大小 mtd.init(); if ( 1 ~= (self:crc32check( "u-boot.bin.img")) or 1 ~= (self:crc32check("romfs-x.cramfs.img")) or 1 ~= (self:crc32check("user-x.cramfs.img")) or 1 ~= (self:crc32check("web-x.cramfs.img")) or 1 ~= (self:crc32check("slave-x.cramfs.img")) or 1 ~= (self:crc32check("logo-x.cramfs.img")) or 1 ~= (self:crc32check( "custom-x.cramfs.img")) ) then print("==>Upgrade: crc32check error!"); return false; end self:updatePart(flashPartions["boot"], "u-boot.bin.img"); --mtd.saveenv(); self:updatePart(flashPartions["rootfs"], "romfs-x.cramfs.img"); --self:updatePart(flashPartions["user"], "user-x.cramfs.img"); self:updatePart(flashPartions["web"], "web-x.cramfs.img"); --self:updatePart(flashPartions["slave"], "slave-x.cramfs.img"); self:updatePart(flashPartions["custom"], "custom-x.cramfs.img"); self:updatePart(flashPartions["logo"], "logo-x.cramfs.img"); --self:InstallPlayer("autoplayer.bin"); self:postInstall(); print("==>Upgrade finished."); return true; end return Installer;