uItron内核原理和服务调用--Kernel篇

本文详细介绍了uItron内核的基本概念与功能,包括事件响应、任务调度和服务调用等核心特性。此外,还深入探讨了任务管理、同步与通信机制及中断处理等内容。

转载:http://hi.baidu.com/qinzhispace/item/46a0dfe13131cf216dabb8a7

一:Kernel篇

1.描述:uItron内核,是操作系统的核心,可以实时多任务处理,它有三个主要的概要:
1.1响应事件:(Response to events)认可的事件可以异步的产生,并且可以立即执行一个任务去处理这 
个事件。
1.2任务调度:(Task scheduling)任务的调度依赖于任务的优先级。
1.3执行服务调用(Service call execution)在任务中,为了处理不同的要求,调用服务函数,可以执行适当
的处理。

2.功能:一个应用程序可以利用服务函数去实现大部分内核的功能
2.1任务管理功能:当一个任务在执行的时候,CPU被分配给这个任务,由内核控制CPU分配的指令和任务
的开始和结束,多任务可以利用共享堆栈的方法共用一个堆栈。
2.2任务同步管理功能:为任务执行基本的同步处理,例如,执行任务的挂起,恢复和任务事件的标志位处理。
2.3同步和通讯管理功能:利用事件标志位(event flag),信号量(semaphres),队列(data queue)和
邮箱(mailbox)可以为为内部的任务实现同步和通讯。
2.4扩展同步和管理功能:利用互斥(mutex),消息缓存(message buffer)也可以为内部实现同步和通
讯。
2.5内存池管理功能:在用户的系统里,管理没有被用过的内存作为一个内存池,一个任务动态取得的块石
来自于内存池,并且可以归还个内存池,作为内存池的大小可以是固定的或者是可变的。
2.6时间管理功能:为系统管理与时间相关联的信息,为了控制的目的,还要监听任务的时间。
2.7系统状态管理功能:执行系统状态功能,例如,修改或者查询环境和系统状态。
2.8中断管理功能:开始时适当的中断处理响应外部中断,这个中断处理执行适当的中断处理,并且通报任
务的中断。
2.9服务调用管理功能:定义或者调用一个扩展的服务调用。
2.10系统配置管理功能:执行系统配置管理功能,例如定义CPU异常handler和读内核版本号。
2.11DSP/FPU支持:在多任务处理环境中,支持DSP/FPU,每个任务可用特殊地注册去执行D/F指令。

3.处理单元(Processing Units)一个应用程序被执行在下列的处理单元中
3.1任务(Task):一个任务是一个处理单元,有多任务处理控制。
3.2任务异常处理程序(Task Exception Processing Routine)当一个任务通过任务异常处理调用函数要求异常处理的时候,这个任务异常处理程序会被执行。
3.3中断Handler(Interrupt Handler):当一个中断发生的时候,一个中断Handler会被执行。
3.4CPU异常Handler(CPU Exception Handler ):当一个CPU异常发生的时候,一个CPU异常Handler会被执行。
3.5Time Event Handler(Cyclic Handler,Alarm Handler,Overrun Handler)当一个特殊的循环或者时间到了的时候,一个时间事件Handler会被执行。
3.6Extended Service Call:扩展服务调用。

4.优先级(Precedence):每个处理单元按一下的优先级顺序被执行:
中断Handler,Time event handler,CPU exection handler,Dispatche ,Task,任务异常处理。
4.1中断Handler(Interrupt handler),时间事件(Time event handler)和CPU异常处理Handler(CPU Excepion handler)它们的优先级处理:当有高优先级中断发生,中断Handler就会变成优先级最高的这个。一个时间事件Handler优先级与一个定时中断时一个级别。
4.2分派(Dispatcher):分派是内核处理过程,是由内核转换一个任务去执行。
4.3任务(Task):任务的遇险记依赖于任务的优先级定义。
4.4任务异常处理(Task Exception Process):任务异常处理程序的优先级比该任务高,比其它高优先级任务低。
4.5特殊情况:当以下的服务函数被调用,优先级不使用上面的情况:
4.5.1当dis_dsp被调用,这个优先级在上面提到的4.1和4.2之间,利用dis_dsp这个状态返回到从前的状态。
4.5.2当loc_cpu或者iloc_cpu被调用,这个优先级是与Interrupt handler一致的,这个interrupt handler的级别与CFG_KNLMSKLLL一致。调用unl_cpu或者iunl_cpu状态会返回到从前的状态。
4.5.3当这个interrupt mask级别被改变除了0以外,利用chg_ims这个优先数同interrupt handler一样,是同一个级别。

5.系统状态(System state):系统状态定义了以下几个状态:任务环境状态/无任务环境状态;可执行分派状态/不可执行分派状态;CPU-locked状态/CPU-unlocked状态。
5.1任务环境状态和无任务环境状态:在系统被执行,无论在任务环境状态或者无任务环境状态下,任务和无任务环境状态之间的不同之处在下面的表1中:
Item Task Context State Non-Task Context State Available service calls Service calls that can be called from the task context Service calls that can be called from the non-task context Task scheduling Refer to Does not occur

以下的处理被执行且在无任务环境中:Interrupt handler;CPU exception handler;Time event handler(cyclic handler,alarm handler,overrun handler);调用chg_ims服务函数去改变interrupt mask的值(除了0以外)的地方。
5.2分派不可以的状态和分派可以的状态(Dispatch-disable State/Dispatch-enable State)系统无论是放置在不可以分派的状态下还是可以分派的状态下。在不可以分派的状态下,任务调度是不允许的,在任务处于WAITING的状态下, 调用服务函数是没有用的。
在任务执行期间,用这个dis-dsp服务调用函数可以将系统状态变为分派不可以的状态,用这个ena_dsp服务函数将要返回系统的状态到分派可以的状态,用这个sns_dsp服务函数,可以检查系统状态是在分派不可以的状态或者是分派可以的状态。
总结:在dispatch-disable和dispatch-enable的过程中是独占cpu的使用时间,这段时间,任务不可以调度。
5.3CPU-locked状态和CPU-unlocked状态
系统无论放置在CPU-Locked状态或者CPU-Ulocked状态下,在cpu-locked的状态下,中断和任务调度是不允许的。注意,无论如 何,如果在配置中,中断的mask级别比那个专用的任务级(CFG_KNLMASKLVE)高,这样是允许的,在这个状态下,在任务处于WAITING状 态下调用服务函数是无用的。

在任务执行期间,用loc_cpu或者iloc_cpu函数可以将系统的状态变为CPU-Locked状态,用unl_cpu或者iunl_cpu函数可 以将系统的状态返回到CPU-Onlocked状态,另外用sns_loc函数可以检查系统状态是CPU-Locked状态或者不是。

6.对象(objects)
对象是被服务函数操作的任务和信号量,对象也会被标识为ID号或者object号,在配置中最大的号能被指定给几乎所有的object。

7任务(Task)
在实时多任务处理,用户按照设置的任务准备一个应用程序,这个程序能够独立地,平行地被执行。
利用服务函数,可以使一个任务与其他任务之间通信,利用外围设备或mcu,服务函数可以被用作是kernel处理事件异步的发生。
7.1任务的状态和转变(Task State and Trunsition)
在用户的系统里,任务可以处于一下七种状态:
7.1.1不存在的状态(NON-EXISTENT State):一个任务还没有在Kernel注册,是一个虚拟的状态。
7.1.2睡眠状态(DORMANT State):一个任务虽然在Kernel注册,但是还没被初始化或者已经被终止。
7.1.3就绪状态(READY State):一个执行的任务在队列中等待CPU的资源分配,因为有其它更高优先级的任务正在执行。
7.1.4运行状态(RUNNING State):这个任务当前正在运行,随着这个高优先级的,在运行状态,Kernel也放置一个就绪(READ)的任务。
7.1.5等待状态(WAITING State):当一个任务不能长时间的继续执行,调用服务函数tslp_tsk(),会使自己睡眠,当调用服务函数wup_tsk()的时候,这个任务就会从WAITING(sleep)状态被唤醒,即这个任务转换为就绪(READ)状态。
7.1.6挂起状态(SUSPENDED State):另一个任务利用服务调用函数sus_tsk()可以使一个任务挂起。
7.1.7等待-挂起状态(WAITING-SUSPENDED State):这个状态是WAITING状态和SUSPENDED状态的合并状态。
附:任务状态的转换图:

7.2任务创建(Task Creation)
任务创建的意思是任务从不存在的状态编程睡眠状态,(Non-existent->Dormant)用哪一种方式创建任务,这个方法就会改变堆栈的使用类型。
参见:任务创建图表(表一)

7.3任务开始(Task Initiation)
一个任务的开始时将任务的睡眠状态编程就绪状态,(Dormant->Ready)
7.3.1一个任务的开始可以用以下两种方法:
@1调用服务函数:act_tsk(),sta_tsk()
@2当一个任务被创建的时候,用特定的TA_ACT作为任务的属性。
7.3.2在任务开始的时候,kernel执行以下的过程:
@1初始化这个任务的base priority和current priority。
@2清除任务wake-up要求的数量。
@3清除任务suspension要求的嵌套的数量。
@4清除挂起(pended)的任务异常来源。
@5设置任务异常处理为不可以的状态。
@6设置任务event flag为0.
说明:以下的参数被传递给任务
@1当TA_ACT作为创建任务的属性的时候和这个任务有act_tsk()开始的时候,这个人在任务创建制定的扩展信息会被传递个任务。
@2当这个任务是由sta_tsk()开始的时候,这个通过sta_tsk()指定的任务开始Code(stacd)会被传递给任务。

7.4任务调度(Task Scheduling)
@1时序调度(Scheduling):任务的时序安排的意思是kernel确定执行的任务执行次序,也就是说,这个次序是有cpu分配给任务,就是READY.kernel选择一个Ready的任务,并且将它置为RUNNING状态,如果没有就绪(READY)的任务,kernel进入空闲状态,取消中断masking并且进入一个无线循环中,等待由中断唤醒的任务,当有许多的任务处于就绪(READY)状态,那么执行的次序就是由cpu分配的wait queue或者ready queue决定的。
为了每一个任务的优先级,(优先级相同的情况下)这有一个ready queeu,每一个queeue操作时按FCFS(First-come,first-served),数值越低,优先级就越高。
@2反转调度(Round-Robin Scheduling)
kernel也支持Round-Robin Scheduling,在cpu分配的相同级别优先级的任务地方,在一个特殊期间,可以通过反转ready queue。用rot_red()函数操作。通过rot_req()函数,在特殊的循环里,执行的次序在一个特殊的期间(具有优先级相同的任务)是可以选择的。
参见:反转任务优先级
@3限制调度(limitation to scheduling)
当系统进入由dis_dsp函数实现的dispatch-disable状态,这个时候任务是不可调度的。
当系统进入由ena_dsp()函数实现的dispatch-enable状态,这个时候任务是可以调度的。
当系统进入由loc_cpu()函数实现的cpu-locked这个时候的任务的调度和所有的中断(除了kernel管理的中断)都是不可以调度的。
当系统进入由unl_cpu()函数实现的cpu-unlocked这个时候的任务调度和中断都是可以的。

附:反转任务优先级


附:任务创建图表(表一)
The method of creating task Kinds of stack which the task created uses static stack Dynamic stack cre_tsk,acre_tsk Service calls √ vscr_tsk Service calls √ By Configruator √ √

7.5任务的终止和删除(Task Ternination and Deletion)
任务终止的意思是一个任务完成之后,进入睡眠状态或者不存在的状态

ext_tsk():从调用的任务中正常退出,是其从运行状态变为睡眠状态。
exd_tsk():使调用的任务正常退出,并将其删除,这个函数将任务从运行状态编程不存在的状态。
ter_tsk():强制终止tskid指定的任务,使其从READY_WAITING,WAITING_SUSPENDED,SUSPENDED状态
变为DORMANT状态。

当一个任务被终止和又被重新开始或者当开始要求queues的数值(act_tsk()服务调用时指定的)除了0,任务就会从最初始的状态开始。

当一个任务不能长久的被用或者当重新分配这个任务ID给其它的任务时,这个exd_tsk()服务调用会被使用,并且将任务不存在的状态,这个ID能够马上被分配给其它的任务,一个任务必须在它执行完了之前释放它的资源,注意,当一个任务被终止和删除,那个Mutex会被unlocked。

当一个任务被终止的时候,kernel执行以下过程:
@1解开被当前任务锁上的互斥。
@2清除上限处理时间(the upper limit processor time)

当一个任务被删除的时候,kernel执行以下过程:
@1释放任务堆栈区域。

7.6任务堆栈(Task Stack)
有三种方式占用堆栈
@1静态堆栈(Static Stack)当系统被配置的时候,静态的堆栈就会通过配置被定义为每一个任务用一个单一的堆栈为多个任务利用,即允许更多的任务去一个共享堆栈是可以使用静态堆栈。
@2动态堆栈(Dynamic Stack)当一个任务被创建,是kernel分配堆栈区域给这个任务,这个堆栈是从动态堆栈区域分配的,一个共享堆栈(使用动态堆栈)不能被多个任务利用。
@3应用程序占用堆栈(Stack Occupied by application only in HI7000H)在任务创建的时候,应用程序占用的堆栈是特殊的地址,共享堆栈功能(用动态堆栈)不可以为多个任务利用。

说明:配置文件指定了一个最大的任务ID(CFG_STSTKID),随着描述最大号的任务使用静态堆栈,这个最大任务ID(CFG_MAXT_SKID)在系统里。
任务ID在1和CFG_STSTKID之间使用静态堆栈,然而,任务ID在CFG_STSTKID+1和CFG_MAXTSKID之间使用动态堆栈或者由应用程序占用,如果CFG_STSTKID被指定为0,那么久无静态的堆栈被使用,如果CFG_STSTKID和CFG_MAXTSKID被指定同样的值,那么所有的任务都会使用顶台堆栈。

7.7共享堆栈功能(Shard Stack Function)
多任务可以共享一个静态堆栈,这样减少了总堆栈空间。
共享堆栈和静态堆栈的分配时有配置文件定义的。然而,在共享一个堆栈的任务组里的任务,是仅仅有一个在每一次被执行的时候。当多个任务开始和共享一个堆栈的时候,首先开始的任务首先使用这个堆栈,剩下的任务进入共享堆栈wait状态,在共享堆栈等待状态的任务一先进先出(FIFO)队列来管理,不管他们的优先级,任务被送到共享堆栈(shared-stack)wait queue。为了他们的开始。
当任务的状态为DORMANT的时候,共享堆栈就会从这个任务中释放,当有多个任务正在等待这个共享堆栈,在等待队列头的任务将会使用这个堆栈和进入READY状态。

附:对共享堆栈功能和转换图(图一)

7.8任务执行模式(Task Execution Mode)

在一些情况中,一个任务可以强制终止一个在还没释放它所有使用的资源之前的任务.(ter_tsk)另外,在一些情况下,一个任务可以被强制地终止(sus_tsk),用vchg_tmd函数可以mask(屏蔽)ter_tsk或者sus_tsk.

7.9排它控制(Exclusive Control)

在一些情况中,在一个任务执行期间,这个任务也许需要排除其它程序。例如,当任务A和中断处理程序B都需要对一个全局变量进行查询和修改,这个时候,查询和修改必须是排它的.即独占。可以排它的控制程序可以是一个中断handler或者是指定的任务。

参见:排他控制表(表一)


7.10任务事件标志位(Task Event Flags )

任务事件标志位是任务的一种模式,一个任务可以等待一个指令.设置的bit为当前任务,也就是说,它可以等待一个指令事件的发生。

参见:Task event flag用例(图一)

8.任务异常处理(Task Exception processing )

当一个任务在执行期间,发生一个异常,那么就会执行异常处理,任务异常处理的执行与任务的处理时异步的,是异步处理,与通常所说的"signal"功能相似.可以在配置的时候定义。

参见:任务异常处理用例(图二)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
排他控制表(表一)
Exclusive ControlInhibited InterruptsTask SchedulingEnter the CPU-Locked state by issuing (loc_cpu)Equal to ro lower than the 

kernel interrupt mask level

NoneMask interrupts by issuing (chg_ims)service call 

when the chg_ims service call is issued from the

task context state,the execution becomes the

non-task context state

Equal to or lower than the

kernel interupt mask level

NoneEnter disable-dispatch state by issuing dis_dsp service callNoneNoneExclusive Control by semaphoreNoneThe kernel schedules tasks;however in tasks

ussing the same seamphore,the number of tasks entering the READYstate.simultaneously 

is limited to the semphore in initial count value

Exclusive Control by mutexNoneThe kernel schedules tasks;however tasks ussing

the same mutex cannot enter the READY state simultaneously.In addition,In tasks using the same mutex,the task priority inversion will not occur

Task event flag用例(图一)


描述:粗线表示执行过程,随着时间关系,Task event flag 的操作

1.任务a调用rclr_tfl(),清除所有的在它任务事件标志位

2.任务a调用vwai_tfl(),等待一个事件

3.任务b调用vset_tfl()(set pattern = 1)给任务a,因为这个设置模式被包含在任务a等待的模式,因此任务a的WAITTING状态取消,并且任务a事件标志位被清零

4.中断handle c调用irset_tlf(),(set pattern = 7)去设置任务a的事件标志位,在这种情况下,然而,随着一个vset_tfl()指定的模式,任务a不等待事件,因此这个任务事件标志位被逻辑或运算(ORed)终止

任务异常处理用例(图二)

描述:字母为操作顺序

a.任务a允许一个任务异常

b.一个异常(异常因子factor = 00000101 )被要求从任务a中,经由这个ras_tex()服务调用,在任务a执行期间

c.当任务a被预定执行的时候,任务的异常处理程序就会在任务a的主要程序被执行之前便开始了,在任务异常处理期间,任务进入任务异常处理不可以的状态,并且任务异常源被清除

d.从任务异常处理程序返回后,任务a的主要程序会被恢复


9.同步和通讯(Synchronization and Communication )

为了能够使任务之间同步和通讯,有以下几个方式:

a.Semaphores(信号量)排他或者独占控制资源

b.Event flags(事件标志位)等待several事件和同步任务操作

c.Data queues(数据队列)传递数据(Passes 1-word data)

d.MailBox(邮箱)传递数据(Passes data address)

e.Mutex(互斥)排他或独占控制一个Single一员(单一)

9.1信号量(Semaphore)

是任务执行被要求的资源元素,这些元素包含任务与硬件之间的内容共享。例如I/O,一个信号量是一个对像,通过表示实物和资源个数提供排他控制和同步功能,在这种情况下,任务必须被创建,为了分开一个任务空间,这个任务被排他访问,通过调用wai_sem()和sig_sem()。通常可以被利用的资源个数在初始化的时候被定义。

参见:Example of using Semaphore用例(图一)

描述:粗线是表示执行过程,虚线表示任务可以独占排他方位资源的区域

a.任务a通过cre_sem()创建一个信号量,开始时信号量个数是2(semaphore = 2)

b.任务a通过wai_sem得到一个信号量,消耗了信号量:个数为1(semaphore = 1)任务a继续执行

c.任务b调用wai_sem()

d.任务c调用wai_sem(),但是不能得到一个信号量,因为信号量的个数已经是0了,并且任务进入WAITING状态

e.任务a调用sig_sem()释放一个信号量,这个释放的信号量被任务c占有,那么任务c从WAITING状态释放进入READY状态

f.任务b地啊用sig_sem()释放一个信号量,因为没有任务在等待信号量,所以信号量的计数被指定为1

9.2事件标志位(Event flag)

一个event flag是一组按位组合的数去相应某个事件.一个事件相应一个位,任务可以等待一个event flag中设定的一个指定的位,也就是说,任务可以等直到这个指定的事件发生

参见:Example of using an Event flag用例(图二)

描述:粗线是表示执行过程,以下是描述event flag的操作与时间的关系

a.任务a通过cre_flg()创建一个event falg.TA_CLR属性(当WAITING状态释放,清除event flag为0),被指定并且开始时各个为指定的值都是0

b.任务a通过wai_flg()(waiting pattern = 3,AND wait)去等待一个事件

c.任务b通过set_flg()(set pattern = 7)因为任务a正在等待被设置,所有的位.任务a从WAITING状态释放,另外,因为被指定TA_CLR这个属性,这个event flag被清0

d.中断handler C通过iset_flg()(set pattern = 1)设置event flag,在这种情况下,这没有任务等待事件,并且event flag是(ORed)与操作和这个通过iset_flg()指定的pattern.




/****************************************************************************** * Copyright (c) 2018-2018 TP-Link Technologies CO.,LTD. * * Filename: fw_upgrade.c * Version: 1.0 * Description: Check and Upgrade firmware, including kernel, romfs, isp_config * Author: yexuelin<yexuelin@tp-link.com.cn> * Date: 2018-12-15 ******************************************************************************/ #define _GNU_SOURCE #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/reboot.h> #include <sys/shm.h> #include <errno.h> #include "common.h" #include "nsd_common.h" #include "slp_model.h" #include "flashio.h" #include "libds.h" ////#include "libctaocrypt/md5.h" ////#include "libctaocrypt/rsa.h" ////#include "libctaocrypt/coding.h" ////#include "libctaocrypt/sha.h" #include "sslApi.h" #include "idle_worker.h" #include "lock_text.h" #ifdef FACTORY_BOOT_SDCARD_RECOVERY #include "sd_backup.h" #endif #include "rsaVerify.h" #define UP_HEADER_ELE(ele) ((rsaSignatureProtocol == 2) ? ((UPGRADE_HEADER_RSA2048*)buf_start)->ele : ((UPGRADE_HEAD*)buf_start)->ele) #define HEAD_SIZE ((rsaSignatureProtocol == 2) ? (sizeof(UPGRADE_HEADER_RSA2048)) : (sizeof(UPGRADE_HEAD))) static uint32_t uhTagLength = 0; #define VERIFY_STAT_SUCCESS 1 #define VERIFY_STAT_FAIL 2 #define DOWNLOAD_FW_SUCCESS 2 /* 注意 p 是网络字节序 */ #define BIT_VAL(p, index) ((*(p + (index >> 3)) >> (7 - (index & 0x7))) & 0x1) #define WORD_ALIGN(p) (((U32)(p) + 3) & ~3) #define FW_KEY_PATH "/www/cert/firmware/firmware-pub-key.pem" #define FW_KEY_PATH_2048 "/www/cert/firmware/firmware-pub-key.rsa2048key" #define UG_RSA_KEY_PEM_LEN 2048 #define UG_RSA_KEY_DER_LEN 1024 #define ASN1_LEN sizeof(g_asn1_weird_stuff) #define SHA1_HASH_LEN 20 #ifdef SYSUPGRADE_CHECK_RSA LOCAL BOOL g_fw_rsa_checking = TRUE; #else LOCAL BOOL g_fw_rsa_checking = FALSE; #endif LOCAL char* g_upgrade_mmap_addr = NULL; LOCAL S32 g_upgrade_file_size = 0; LOCAL int g_upgrade_file_fd = -1; LOCAL EXE_UPGRADE_PARAM g_upgrade_param = {0}; static int rsaSignatureProtocol = 1; static int align_size = 0; static int ubootNoUpgrade = 0; typedef struct _upgrade_method { EXECUTE_UPGRADE_TYPE upgrade_type; S32 (*method)(UPGRADE_MSG *msg); }UPGRADE_METHOD; LOCAL const U8 g_asn1_weird_stuff[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14, }; LOCAL const U8 g_blk_hdr_magic_num[] = {0x12, 0x34, 0x56, 0x78}; /* Global variable for firmware upgrade */ LOCAL U8 kern_and_romfs_changed = 0; LOCAL U8 boot_changed = 0; LOCAL U8 fdt_changed = 0; //fdt LOCAL unsigned char upgrade_header_magic[MAGIC_LEN] = { 0x55, 0xAA, 0x4C, 0x5E, 0x83, 0x1F, 0x53, 0x4B, 0xA1, 0xF8, 0xF7, 0xC9, 0x18, 0xDF, 0x8F, 0xBF, 0x7D, 0xA1, 0xAA, 0x55 }; /* calculate md5 with data and size, put result to *md5_value */ LOCAL S32 calc_md5(U8 *data, S32 size, U8 *md5_value) //用data和size计算md5,将结果代入*md5_value { if (NULL == data || NULL == md5_value || size <= 0) { UPGRADE_ERROR("Invalid MD5 argument."); return ERROR; } Md5 md5; tpssl_InitMd5(&md5); tpssl_Md5Update(&md5, data, size); tpssl_Md5Final(&md5, md5_value); return OK; } #if 0 LOCAL void print_arr_hex(char *text, int len, U8 arr[]) { char buf[64]; int i; char *p = buf; for (i = 0; i < len; i++) p += sprintf(p, "%x,", arr[i]); UPGRADE_ERROR("%s: %s", text, buf); } #endif /* ------------------------------------------------本地 Firmware 信息获取--------------------------------------------*/ /* 本地 Firmware 信息的初始化,读取本地 tp_header 和 factory info * * @context: origin_info, 保存本地 firmware 信息的结构体 fac_info, 从 flash 的 factory info 区域读取的信息字符串 * * Return: OK/ERROR, 初始化成功/失败 */ S32 origin_info_init(ORIGIN_FW_INFO *origin_info) //读取本地固件信息到origin_info { TP_HEAD_INFO origin_tp_head; FACTORY_INFO_DATA fac_info; U32 size; S32 ret; #ifdef CONFIG_LTE_MODULE_IN_UP_BIN MODULE_SPEC module_spec; LTE_PARAM_MODULE_INFO lte_module_info; #endif if (NULL == origin_info) { goto INIT_ERROR; } memset(origin_info, 0, sizeof(ORIGIN_FW_INFO)); memset(&origin_tp_head, 0, sizeof(TP_HEAD_INFO)); memset(&fac_info, 0, sizeof(FACTORY_INFO_DATA)); #ifdef CONFIG_LTE_MODULE_IN_UP_BIN memset(&module_spec, 0, sizeof(MODULE_SPEC)); memset(&lte_module_info, 0, sizeof(LTE_PARAM_MODULE_INFO)); #endif /* 读取 TP HEAD */ size = ds_read(TP_HEADER_PATH, &origin_tp_head, sizeof(TP_HEAD_INFO)); if (size < sizeof(TP_HEAD_INFO)) { UPGRADE_ERROR("Reading TP_HEAD failed."); goto INIT_ERROR; } /* 读取 fac_info */ size = ds_read(FACTORY_INFO_DATA_PATH, &fac_info, sizeof(FACTORY_INFO_DATA)); if (size < sizeof(FACTORY_INFO_DATA)) { UPGRADE_ERROR("Reading FACTORY_INFO_DATA failed."); goto INIT_ERROR; } /* init local partition offsets and lens */ origin_info->tphead_len = ntohl(origin_tp_head.tphead_len); #ifdef FDT_UPGRADE_SUPPORT origin_info->fdt_offset = ntohl(origin_tp_head.fdt_offset); //fdt origin_info->fdt_len = ntohl(origin_tp_head.fdt_len); #else origin_info->fdt_offset = 0; //fdt origin_info->fdt_len = 0; #endif origin_info->uboot_offset = ntohl(origin_tp_head.uboot_offset); origin_info->uboot_len = ntohl(origin_tp_head.uboot_len); origin_info->tphead_offset = ntohl(origin_tp_head.tphead_offset); origin_info->kernel_offset = ntohl(origin_tp_head.kernel_offset); origin_info->vendor_id = ntohs(origin_tp_head.vendor_id); origin_info->zone_code = ntohs(origin_tp_head.zone_code); /* init local partition CRCs */ #ifdef FDT_UPGRADE_SUPPORT memcpy(origin_info->fdt_crc, origin_tp_head.fdt_crc, CRC_LEN); //fdt #endif memcpy(origin_info->factory_info_crc, origin_tp_head.factory_info_crc, CRC_LEN); memcpy(origin_info->radio_crc, origin_tp_head.radio_crc, CRC_LEN); memcpy(origin_info->bootloader_crc, origin_tp_head.uboot_crc, CRC_LEN); memcpy(origin_info->kernel_and_romfs_crc, origin_tp_head.firmware_crc, CRC_LEN); memcpy(origin_info->fw_id, origin_tp_head.fw_id, FW_ID_LEN); /* get BL FwID number and init BL */ origin_info->bl_num = ntohl(origin_tp_head.fw_id_bl_num); memcpy(origin_info->bl_id, origin_tp_head.fw_id_bl, FW_ID_LEN * origin_info->bl_num); /* init hwid */ ret = hex_str_to_bytes(origin_info->hw_id, (char*)fac_info.hw_id, HW_ID_LEN); if (0 != ret) { goto INIT_ERROR; } /* init mac */ memcpy(origin_info->mac, fac_info.mac, MAC_ADDR_SIZE); /* init extFw dev_name: dev_name + _ + hw_ver */ strcpy((char*)origin_info->dev_name, (char*)fac_info.dev_name); size = strlen(fac_info.dev_name); *(origin_info->dev_name + size) = '_'; strcpy((char*)origin_info->dev_name + size + 1, (char*)fac_info.hw_ver); #ifdef CONFIG_LTE_MODULE_IN_UP_BIN /* init lte info */ size = ds_read(MODULE_SPEC_PATH, &module_spec, sizeof(MODULE_SPEC)); if (size < sizeof(MODULE_SPEC)) { UPGRADE_ERROR("Reading module_spec failed."); goto INIT_ERROR; } origin_info->lte_supported = atoi(module_spec.lte); if (origin_info->lte_supported) { size = ds_read(LTE_MODULE_INFO_PATH, &lte_module_info, sizeof(LTE_PARAM_MODULE_INFO)); if (size < sizeof(LTE_PARAM_MODULE_INFO)) { UPGRADE_ERROR("Reading lte module info failed."); goto INIT_ERROR; } strncpy((char *)origin_info->lte_vender, (const char *)lte_module_info.vender, sizeof(origin_info->lte_vender)); strncpy((char *)origin_info->lte_product, (const char *)lte_module_info.product, sizeof(origin_info->lte_product)); origin_info->lte_version = atoi(lte_module_info.version); } #endif return SLP_ENONE; INIT_ERROR: return SLP_ESYSTEM; } /* ------------------------------------------------ISP 检查,更新和控制句柄结构体--------------------------------------*/ /* 检查是否为默认 ISP */ LOCAL S32 isp_partition_is_default(ISP_HEADER *origin_isp_hdr) //判断入参是否默认值(即全为 0xFF) { ISP_HEADER default_value; memset(&default_value, 0xFF, sizeof(ISP_HEADER)); //default value for ISP is FF when mkslpfw return memcmp(origin_isp_hdr, &default_value, sizeof(ISP_HEADER)); } /* 从 factory info 判断 mac 是否为默认 */ LOCAL S32 mac_is_default(U8 *mac) //判断 mac 是否为默认(0) { U8 mac_default[MAC_ADDR_SIZE]; if (NULL == mac) { return ERROR; } /* default mac value in factory info is all 0 when mkslpfw */ memset(mac_default, 0, sizeof(mac_default)); if (0 == memcmp(mac_default, mac, MAC_ADDR_SIZE)) { return OK; } return ERROR; } /* 检查 isp 内容的合法性和是否为最新 */ LOCAL S32 chk_fw_isp(BLOCK_HEADER* blk_hdr, void* this_handler, ORIGIN_FW_INFO *origin_info) //固件升级过程中对 ISP检查 { S32 ret = 0; S32 i = 0; S32 blk_num = 0; char md5_tmp[MD5_DIGEST_SIZE] = {0}; ISP_HEADER origin_isp_hdr; ISP_HEADER* i_hdr = NULL; EXT_FW_BLOCK_HANDLER* ext_handler = this_handler; if (NULL == blk_hdr || NULL == this_handler) { UPGRADE_ERROR("NULL pointer!"); ret = SLP_EFWEXCEPTION; goto out; } /* 跳过了 BLOCK_HEADER, extFw 的开始, extFw: ISP_HEADER + extFw file */ U8* ext_fw_base = (U8*)blk_hdr + sizeof(BLOCK_HEADER); blk_num = ntohl(blk_hdr->num); memset(&origin_isp_hdr, 0, sizeof(ISP_HEADER)); /* 从 radio flash 中读取 ISP_HEADER */ ret = flash_read_radio((U8*)&origin_isp_hdr, sizeof(ISP_HEADER)); if (OK != ret) { UPGRADE_ERROR("read flash failed"); goto out; } if (0 == isp_partition_is_default(&origin_isp_hdr)) //如果是默认值 { UPGRADE_DEBUG("Isp partition is default"); if (OK == mac_is_default(origin_info->mac)) //如果mac是默认值 { /* use default device name in factory info, to match isp */ UPGRADE_DEBUG("Mac is default"); memcpy(origin_isp_hdr.dev_name, origin_info->dev_name, EXT_FW_DEVNAME_LEN); } else { UPGRADE_ERROR("Isp partition is default but mac is not default"); return SLP_EFWNOTSUPPORTED; } } for (i = 0; i < blk_num; i++) { if (CONTENT_TYPE_ISP_CONFIG == ntohl(blk_hdr->info[i].type)) { i_hdr = (ISP_HEADER*)ext_fw_base; #ifdef USES_LITTLEFS if (ntohl(i_hdr->compress_type) == COMPRESS_TYPE_LFS) { memset(&origin_isp_hdr, 0, sizeof(ISP_HEADER)); FILE* fp = NULL; fp = fopen("/tmp/base-files/isp_header", "r"); if (NULL == fp) { ret = SLP_ESYSTEM; goto out; } fread(&origin_isp_hdr, 1, sizeof(ISP_HEADER), fp); fclose(fp); if (0 == memcmp(i_hdr->dev_name, origin_isp_hdr.dev_name, EXT_FW_DEVNAME_LEN)) { UPGRADE_DEBUG("lfs: block name=%s\n", i_hdr->dev_name); ext_handler->block = i_hdr; ext_handler->need_upgrade = EXT_FW_CHANGED; ret = SLP_ENONE; goto out; } } #endif if (0 == memcmp(i_hdr->dev_name, origin_isp_hdr.dev_name, EXT_FW_DEVNAME_LEN)) { ext_handler->block = i_hdr; UPGRADE_DEBUG("isp: device name supported"); UPGRADE_DEBUG("device_name = %s", origin_isp_hdr.dev_name); UPGRADE_DEBUG("strlen(origin_isp_hdr.dev_name) = %d", strlen((char*)(origin_isp_hdr.dev_name))); break; } } ext_fw_base += ntohl(blk_hdr->info[i].length); } if (i == blk_num) { UPGRADE_ERROR("isp: device name not supported"); ret = SLP_EFWNOTSUPPORTED; goto out; } calc_md5((U8*)i_hdr + sizeof(ISP_HEADER), ntohl(i_hdr->isp_length), (U8*)md5_tmp); ret = memcmp(i_hdr->isp_CRC, md5_tmp, MD5_DIGEST_SIZE); if (ret) { UPGRADE_ERROR("Invalid isp data in firmware"); goto out; } ret = memcmp(&(i_hdr->isp_ver), &(origin_isp_hdr.isp_ver), sizeof(U32)); if (ret) { UPGRADE_DEBUG("isp is changed"); ext_handler->need_upgrade = EXT_FW_CHANGED; ret = SLP_ENONE; goto out; } ret = memcmp(i_hdr->isp_CRC, origin_isp_hdr.isp_CRC, CRC_LEN); if (ret) { UPGRADE_DEBUG("isp is changed"); ext_handler->need_upgrade = EXT_FW_CHANGED; ret = SLP_ENONE; goto out; } ret = memcmp(i_hdr->sw_ver, origin_isp_hdr.sw_ver, SW_VER_LEN); if (ret) { UPGRADE_DEBUG("isp is not changed but software version is changed"); ext_handler->need_upgrade = EXT_FW_CHANGED; ret = SLP_ENONE; goto out; } UPGRADE_DEBUG("isp is not changed"); out: return ret; } /* 升级 extFw */ LOCAL S32 upgrade_fw_isp(ISP_HEADER* block) //isp升级 { S32 ret = 0; U8* isp_buf; U32 block_size = 0; U32 isp_max_size = get_radio_size(); if (NULL == block) { UPGRADE_ERROR("NULL pointer"); ret = SLP_EFWEXCEPTION; return ret; } block_size = ntohl(block->isp_length) + sizeof(ISP_HEADER); if (block_size > isp_max_size) { UPGRADE_ERROR("Not enough ROM for ispconfig"); return SLP_ESYSTEM; } #ifdef USES_LITTLEFS if (COMPRESS_TYPE_LFS == ntohl(block->compress_type)) { FILE *fp = NULL; fp = fopen(LFS_TAR_FILE_PATH, "w"); if (fp == NULL) { UPGRADE_ERROR("open file[%s] error", LFS_TAR_FILE_PATH); return SLP_ESYSTEM; } ret = fwrite((U8 *)block + sizeof(ISP_HEADER), 1, ntohl(block->isp_length), fp); fclose(fp); if (ret != ntohl(block->isp_length)) { UPGRADE_ERROR("write file[%s] error, filesize is %d, ret=%d", LFS_TAR_FILE_PATH, ntohl(block->isp_length), ret); return SLP_ENOMEMORY; } else { UPGRADE_DEBUG("isp block size is %d\n", ntohl(block->isp_length)); } char cmd[512] = {0}; snprintf(cmd, 512, "tar -zxvf %s -C /tmp/base-files", LFS_TAR_FILE_PATH); system(cmd); return SLP_ENONE; } #endif isp_buf = (U8*)UPGRADE_MALLOC(isp_max_size); if (NULL == isp_buf) { UPGRADE_ERROR("Not enough memory for isp_buf"); return SLP_ESYSTEM; } memset(isp_buf, 0xff, isp_max_size); memcpy(isp_buf, (U8*)block, block_size); ret = flash_write_radio(isp_buf, isp_max_size); if (OK != ret) { UPGRADE_ERROR("write radio flash failed."); UPGRADE_FREE(isp_buf); return SLP_ESYSTEM; } UPGRADE_DEBUG("upgrade isp done"); UPGRADE_FREE(isp_buf); return SLP_ENONE; } #ifdef CONFIG_LTE_MODULE_IN_UP_BIN LOCAL S32 chk_lte_fw(BLOCK_HEADER* blk_hdr, void* this_handler, ORIGIN_FW_INFO *origin_info) //lte检查 { S32 ret = 0; S32 i = 0; S32 blk_num = 0; char md5_tmp[MD5_DIGEST_SIZE] = {0}; EXT_FW_BLOCK_HANDLER* ext_handler = this_handler; ISP_HEADER* ext_header = NULL; U8 lte_dev_name[LTE_VENDER_LEN + LTE_PRODUCT_LEN + 1] = {0}; U8* ext_fw_base = NULL; if (NULL == blk_hdr || NULL == this_handler || NULL == origin_info) { UPGRADE_ERROR("lte_fw: NULL pointer!"); ret = SLP_EFWEXCEPTION; goto out; } /* 跳过了 BLOCK_HEADER, extFw 的开始, extFw: ISP_HEADER + extFw file */ ext_fw_base = (U8*)blk_hdr + sizeof(BLOCK_HEADER); ext_handler->need_upgrade = EXT_FW_NOT_CHANGED; blk_num = ntohl(blk_hdr->num); snprintf((char *)lte_dev_name, sizeof(lte_dev_name), "%s_%s", origin_info->lte_vender, origin_info->lte_product); for (i = 0; i < blk_num; i++) { if (CONTENT_TYPE_LTE_FW == ntohl(blk_hdr->info[i].type)) { ext_header = (ISP_HEADER*)ext_fw_base; if (0 == strcasecmp((const char *)lte_dev_name, (const char *)ext_header->dev_name)) { ext_handler->block = ext_header; UPGRADE_DEBUG("lte_fw: device name %s(%u) supported", ext_header->dev_name, ntohl(ext_header->isp_length)); break; } if (0 == strcasecmp((const char *)lte_dev_name, "_")) { ext_handler->block = ext_header; UPGRADE_WARNING("lte_fw: device name %s supported, curr fw name %s", ext_header->dev_name, lte_dev_name); break; } } ext_fw_base += ntohl(blk_hdr->info[i].length); } if (i == blk_num) { UPGRADE_ERROR("lte_fw: device name not supported"); ret = SLP_EFWNOTSUPPORTED; goto out; } calc_md5((U8*)ext_header + sizeof(ISP_HEADER), ntohl(ext_header->isp_length), (U8*)md5_tmp); ret = memcmp(ext_header->isp_CRC, md5_tmp, MD5_DIGEST_SIZE); if (ret) { UPGRADE_ERROR("lte_fw: MD5 sum not match"); ret = SLP_EFWNOTSUPPORTED; goto out; } if (ntohl(ext_header->isp_ver) != origin_info->lte_version) { UPGRADE_DEBUG("lte_fw: cur_version %d upgrade to version %d", origin_info->lte_version, ntohl(ext_header->isp_ver)); ext_handler->need_upgrade = EXT_FW_CHANGED; ret = SLP_ENONE; goto out; } UPGRADE_DEBUG("lte_fw is not changed"); ext_handler->need_upgrade = EXT_FW_NOT_CHANGED; ret = SLP_ENONE; out: return ret; } LOCAL S32 upgrade_lte_fw(ISP_HEADER* block) //更新lte { S32 ret = SLP_EFWEXCEPTION; LTE_PARAM_UPGRADE_STC upgrade_params_stc = {0}; int interval = 2; LTE_PARAM_UPGRADE upgrade_params; if (NULL == block) { UPGRADE_ERROR("NULL pointer"); return SLP_EFWEXCEPTION; } upgrade_params.fw_buf = (U32)((U8 *)block + sizeof(ISP_HEADER)); upgrade_params.fw_len = ntohl(block->isp_length); upgrade_params.status = E_UPGRADE_READY; ds_write(LTE_UPGRADE_PATH, &upgrade_params, sizeof(upgrade_params)); UPGRADE_DEBUG("notify to upgrade lte fw(%p:%d)", upgrade_params.fw_buf, upgrade_params.fw_len); ds_read(LTE_UPGRADE_STC_PATH, &upgrade_params_stc, sizeof(upgrade_params_stc)); /* read upgrade resulte in timeout time */ while (upgrade_params_stc.upgrade_timeout >= 0) { ds_read(LTE_UPGRADE_PATH, &upgrade_params, sizeof(upgrade_params)); if (upgrade_params.status == E_UPGRADE_COMPLETE) { ret = SLP_ENONE; UPGRADE_DEBUG("upgrade lte fw done successfully"); break; } else if (upgrade_params.status == E_UPGRADE_ERROR) { ret = SLP_EFWEXCEPTION; UPGRADE_ERROR("lte_fw: upgrade failed"); break; } UPGRADE_DEBUG("upgrading lte fw status:%d timeout %d", upgrade_params.status, upgrade_params_stc.upgrade_timeout); sleep(interval); upgrade_params_stc.upgrade_timeout -= interval; } return ret; } #endif #ifdef CONFIG_UITRON_EXT_UPGRADE_SUPPORT LOCAL S32 chk_uitron_ext_fw(BLOCK_HEADER* blk_hdr, void* this_handler, ORIGIN_FW_INFO *origin_info) //Uitron检查 { S32 ret = 0; S32 i = 0; S32 blk_num = 0; U8* uitron_ext_buf=NULL; U32 uitron_ext_size = get_uitron_ext_size(); char md5_tmp[MD5_DIGEST_SIZE] = {0}; char md5_origin[MD5_DIGEST_SIZE] = {0}; /*ISP_HEADER实际上为EXT_FW_HEADER,此时应该改为EXT_FW_HEADER更为恰当*/ ISP_HEADER* i_hdr = NULL; EXT_FW_BLOCK_HANDLER* ext_handler = this_handler; if (NULL == blk_hdr || NULL == this_handler) { UPGRADE_ERROR("NULL pointer!"); ret = SLP_EFWEXCEPTION; goto out; } /* 跳过了 BLOCK_HEADER, extFw 的开始, extFw: ISP_HEADER + extFw file */ U8* ext_fw_base = (U8*)blk_hdr + sizeof(BLOCK_HEADER); uitron_ext_buf = (U8*)UPGRADE_MALLOC(uitron_ext_size); if (NULL == uitron_ext_buf) { UPGRADE_ERROR("not enough memory for uitron_ex"); return SLP_ESYSTEM; } memset(uitron_ext_buf, 0xff, uitron_ext_size); /* 从 uitron_ext中读取uitron_ext */ ret = flash_read_uitron_ext(uitron_ext_buf, uitron_ext_size); if (OK != ret) { UPGRADE_ERROR("read flash failed"); goto out; } blk_num = ntohl(blk_hdr->num); for (i = 0; i < blk_num; i++) { if (CONTENT_TYPE_UITRON_EXT_FW == ntohl(blk_hdr->info[i].type)) { i_hdr = (ISP_HEADER*)ext_fw_base; UPGRADE_DEBUG("uitron_ext: type supported"); break; } ext_fw_base += ntohl(blk_hdr->info[i].length); } if (i == blk_num) { UPGRADE_ERROR("uitron_ext: type not supported"); ret = SLP_EFWNOTSUPPORTED; goto out; } calc_md5((U8*)i_hdr + sizeof(ISP_HEADER), ntohl(i_hdr->isp_length), (U8*)md5_tmp); ret = memcmp(i_hdr->isp_CRC, md5_tmp, MD5_DIGEST_SIZE); if (ret) { UPGRADE_ERROR("Invalid uitron_ext in firmware"); goto out; } calc_md5(uitron_ext_buf, ntohl(i_hdr->isp_length), (U8*)md5_origin); ret = memcmp(md5_tmp, md5_origin, MD5_DIGEST_SIZE); if (ret) { UPGRADE_DEBUG("uitron_ext is changed"); ext_handler->block = i_hdr; ext_handler->need_upgrade = EXT_FW_CHANGED; ret = SLP_ENONE; goto out; } UPGRADE_DEBUG("uitron_ext is not changed"); out: UPGRADE_FREE(uitron_ext_buf); return ret; } LOCAL S32 upgrade_uitron_ext_fw(ISP_HEADER* block) //升级uitron { S32 ret = 0; U8* uitron_ext_buf=NULL; U32 block_size = 0; U32 uitron_ext_size = get_uitron_ext_size(); if (NULL == block) { UPGRADE_ERROR("NULL pointer"); ret = SLP_EFWEXCEPTION; return ret; } block_size = ntohl(block->isp_length); if (block_size > uitron_ext_size) { UPGRADE_ERROR("Not enough ROM for uitron_ext"); return SLP_ESYSTEM; } uitron_ext_buf = (U8*)UPGRADE_MALLOC(uitron_ext_size); if (NULL == uitron_ext_buf) { UPGRADE_ERROR("Not enough memory for uitron_ex"); return SLP_ESYSTEM; } memset(uitron_ext_buf, 0xff, uitron_ext_size); memcpy(uitron_ext_buf, (U8*)block + sizeof(ISP_HEADER), block_size); ret = flash_write_uitron_ext(uitron_ext_buf, uitron_ext_size); if (OK != ret) { UPGRADE_ERROR("write uitron_ext flash failed."); UPGRADE_FREE(uitron_ext_buf); return SLP_ESYSTEM; } UPGRADE_DEBUG("upgrade uitron_ext done"); UPGRADE_FREE(uitron_ext_buf); return SLP_ENONE; } #endif EXT_FW_BLOCK_HANDLER blk_hdr_tbl[] = { { CONTENT_TYPE_ISP_CONFIG, EXT_FW_NOT_CHANGED, NULL, chk_fw_isp, upgrade_fw_isp }, #ifdef CONFIG_LTE_MODULE_IN_UP_BIN { CONTENT_TYPE_LTE_FW, EXT_FW_NOT_CHANGED, NULL, chk_lte_fw, upgrade_lte_fw }, #endif #ifdef CONFIG_UITRON_EXT_UPGRADE_SUPPORT { CONTENT_TYPE_UITRON_EXT_FW, EXT_FW_NOT_CHANGED, NULL, chk_uitron_ext_fw, upgrade_uitron_ext_fw }, #endif { 0, 0, NULL, NULL, NULL } }; /* ------------------------------------------------Firmware 检查相关函数--------------------------------------*/ LOCAL void calc_sha(U8 *content, U32 content_len, U8 *hash) //检查哈希值 { Sha sha; tpssl_InitSha(&sha); tpssl_ShaUpdate(&sha, content, content_len); tpssl_ShaFinal(&sha, hash); } #if 0 LOCAL S32 rsa_public_decrypt(const char *key_pem, U32 key_pem_len, U8 *content_encrypt, U32 encrypt_len, U8 *content_decrypt, U32 decrypt_len) { U32 idx = 0; RsaKey rsa_key; U8 public_key_der[UG_RSA_KEY_DER_LEN] = {0}; U32 public_key_der_len = sizeof(public_key_der); if (0 != tpssl_Base64_Decode((U8*)key_pem, key_pem_len, public_key_der, &public_key_der_len)) { UPGRADE_ERROR("Base64 Decode failed"); return ERROR; } tpssl_InitRsaKey(&rsa_key, NULL); if (0 != tpssl_RsaPublicKeyDecode(public_key_der, &idx, &rsa_key, public_key_der_len)) { UPGRADE_ERROR("Rsa Public Key Decode failed."); goto RSA_VERIFY_ERR; } if (tpssl_RsaSSL_Verify(content_encrypt, encrypt_len, content_decrypt, decrypt_len, &rsa_key) <= 0) { UPGRADE_ERROR("Rsa Descrypt failed."); goto RSA_VERIFY_ERR; } tpssl_FreeRsaKey(&rsa_key); return OK; RSA_VERIFY_ERR: tpssl_FreeRsaKey(&rsa_key); return ERROR; } #endif LOCAL S32 rsa_sign_verify(const char *key_pem, U32 key_pem_len, U8 *sign_content, U32 sign_content_len, U8 *sign, U32 sign_len) //RSA 签名验证 { U8 sign_decrypt[UG_RSA_KEY_DER_LEN] = {0}; U8 sign_buf[RSA_SIGN_LEN] = {0}; U8 sha1_hash[SHA1_HASH_LEN] = {0}; U32 i = 0; for(i = 0; i < sign_len; i++) { sign_buf[i] = sign[sign_len - 1 - i]; } if (OK != tpssl_rsa_public_decrypt(key_pem, key_pem_len, sign_buf, sign_len, sign_decrypt, sizeof(sign_decrypt))) { return ERROR; } for (i = 0; i < ASN1_LEN; ++i) { if (g_asn1_weird_stuff[i] != sign_decrypt[i]) { return ERROR; } } calc_sha(sign_content, sign_content_len, sha1_hash); if (0 != memcmp(sha1_hash, sign_decrypt + i, sizeof(sha1_hash))) { UPGRADE_DEBUG("RSA Signature wrong."); return ERROR; } return OK; } /* 根据 vendorID 验证 RSA 签名 */ LOCAL S32 chk_fw_rsa(UPGRADE_HEAD* up_head, S32 file_size) //验证固件的 RSA 签名 { U8 md5_tmp[MD5_DIGEST_SIZE] = {0}; U8 rsa_tmp[RSA_SIGN_LEN] = {0}; char public_key_pem[UG_RSA_KEY_PEM_LEN] = {0}; S32 public_key_fd = 0; if ((public_key_fd = open(FW_KEY_PATH, O_RDONLY)) <= 0) { UPGRADE_ERROR("No firmware key pem file."); return ERROR; } if (read(public_key_fd, public_key_pem, sizeof(public_key_pem)) < 0) { close(public_key_fd); return ERROR; } close(public_key_fd); memcpy(rsa_tmp, up_head->rsa_sign, RSA_SIGN_LEN); /* backup RSA sign first */ memset(up_head->rsa_sign, 0x0, RSA_SIGN_LEN); if (ERROR == calc_md5((U8*)up_head, file_size, md5_tmp)) { return ERROR; } if (OK != rsa_sign_verify(public_key_pem, strlen(public_key_pem), md5_tmp, sizeof(md5_tmp), rsa_tmp, sizeof(rsa_tmp))) { return ERROR; } /* restore RSA sign */ memcpy(up_head->rsa_sign, rsa_tmp, RSA_SIGN_LEN); UPGRADE_DEBUG("firmware RSA signiture check OK"); return OK; } static int checkFirmwareRSA_2048(UPGRADE_HEADER_RSA2048* uHeader, S32 file_size, unsigned int bOnlyCheck, unsigned int header_align_size) //验证使用 2048 位 RSA 密钥签名的固件 { int signCheckOk = 0; /* for RSA sign check result */ unsigned char rsaTmp[RSA_SIGN_LEN_2048] = {0}; char public_key_pem[UG_RSA_KEY_PEM_LEN] = {0}; S32 public_key_fd = 0; if ((public_key_fd = open(FW_KEY_PATH_2048, O_RDONLY)) <= 0) { UPGRADE_ERROR("No firmware key pem file."); return ERROR; } if (read(public_key_fd, public_key_pem, sizeof(public_key_pem)) < 0) { close(public_key_fd); return ERROR; } close(public_key_fd); memcpy(rsaTmp, uHeader->rsa_sign, RSA_SIGN_LEN_2048); /* backup RSA sign first */ memset(uHeader->rsa_sign, 0x0, RSA_SIGN_LEN_2048); signCheckOk = rsaVerifyPSSSignByBase64EncodePublicKeyBlob( (unsigned char*)public_key_pem, strlen(public_key_pem), (unsigned char*)uHeader, file_size, rsaTmp, RSA_SIGN_LEN_2048, bOnlyCheck, header_align_size); memcpy(uHeader->rsa_sign, rsaTmp, RSA_SIGN_LEN_2048); /* restore RSA sign */ if (!signCheckOk) { UPGRADE_DEBUG("firmware RSA signiture check fail"); return ERROR; } UPGRADE_DEBUG("firmware RSA signiture check OK"); return OK; } /* 检查升级固件支持的 HwID 列表 */ LOCAL S32 chk_fw_hw_list(unsigned short hwIdNum, unsigned char hwIdList[0][HW_ID_LEN], ORIGIN_FW_INFO* origin_info) //检查升级固件支持的 HwID 列表 { S32 i; for (i = 0; i < ntohs(hwIdNum); ++i) { if (0 == memcmp(hwIdList[i], origin_info->hw_id, HW_ID_LEN)) { return OK; } } return ERROR; } #ifdef CONFIG_SYSUPGRADE_CHECK_FWLIST /* check if FwID is in firmware's FL */ LOCAL S32 chk_fw_fl(unsigned short hwIdNum, unsigned char hwIdList[0][HW_ID_LEN], unsigned short fwIdFLNum, unsigned char fwIdFLMask[FWID_FL_MASK_LEN], ORIGIN_FW_INFO *origin_info) //检查当前设备的固件 ID 是否在固件的兼容列表(FL)中 { S32 i; U8 (*fw_id_fl)[FW_ID_LEN] = NULL; U8 *fl_mask = NULL; fw_id_fl = hwIdList + ntohs(hwIdNum); fl_mask = fwIdFLMask; for (i = 0; i < ntohs(fwIdFLNum); i++) { if (0x1 == BIT_VAL(fl_mask, i)) /* FL Mask don't support this FwID */ { if (0 == memcmp(origin_info->fw_id, fw_id_fl[i], FW_ID_LEN)) { UPGRADE_DEBUG("My FwID is in firmware's FL"); return OK; } } } UPGRADE_DEBUG("My FwID is not in firmware's FL"); return ERROR; } /* check if firmware's FwID is in BL of flash */ LOCAL S32 chk_fw_bl(TP_HEAD_INFO *tp_head, ORIGIN_FW_INFO *origin_info) //检查当前固件的 ID 是否在设备的黑名单(BL)中 { S32 i; for (i = 0; i < origin_info->bl_num; ++i) { if (0 == memcmp(origin_info->bl_id[i], tp_head->fw_id, FW_ID_LEN)) { UPGRADE_DEBUG("firmware's FwID is in BL of flash"); return OK; } } UPGRADE_DEBUG("firmware's FwID is not in BL of flash"); return ERROR; } #endif /* check if firmware is really not changed in case of MD5 conflict.*/ LOCAL S32 chk_fw_md5_conflict(enum partition_index partitionIndex, U8* fw_base, S32* conflict) //检测当前固件与设备中已存在的固件是否存在 MD5 冲突,即判断即将升级的固件是否与当前存储在指定分区中的固件完全相同 { /* 每隔1KB起始位置采样1字节共采样16B */ S32 i = 0; const S32 sample_len = 16; U8 sample_buf[sample_len]; if (OK != flash_md5_sample(partitionIndex, sample_buf, sample_len)) { return ERROR; } for (i = 0; i < sample_len; i++) { if (sample_buf[i] != *(fw_base + 1024 * i)) { UPGRADE_DEBUG("md5 conflicted!"); *conflict = 1; return OK; } } *conflict = 0; return OK; } /* 根据 MD5 值判断固件的 kernel and romfs 和 bootloader 是否变化,进而判断是否需要更新相应部分 */ LOCAL S32 chk_fw_partition(char *up_head, unsigned short contentTypes, TP_HEAD_INFO *tp_head, ORIGIN_FW_INFO *origin_info) //根据 MD5 值判断固件的 kernel and romfs 和 bootloader 是否变化,进而判断是否需要更新相应部分 { U32 fw_contents = 0x0; /* firmware content type */ S32 conflict = 0; /* get the content parts of firmware */ fw_contents = ntohs(contentTypes); UPGRADE_DEBUG("fw_contents = 0x%x",fw_contents); /* up_boot.bin only */ #ifdef SLP_CAMERA_SUPPORT /*SLP升级机型需要兼容fw_contents不带JFFS2*/ if (PARTS_UP_BOOT != (fw_contents & PARTS_UP_BOOT) && PARTS_UP_BOOT_WITHOUT_JFFS2 != (fw_contents & PARTS_UP_BOOT_WITHOUT_JFFS2)) #else if (PARTS_UP_BOOT != (fw_contents & PARTS_UP_BOOT)) #endif { /* 当分区标志显示不完整时检测是否仅bootloader分区标志为0,分区完整时fw_contents的值为0x1f */ fw_contents |= CONTENT_TYPE_BOOTLOADER; #ifdef SLP_CAMERA_SUPPORT if (PARTS_UP_BOOT == (fw_contents & PARTS_UP_BOOT) || PARTS_UP_BOOT_WITHOUT_JFFS2 == (fw_contents & PARTS_UP_BOOT_WITHOUT_JFFS2)) #else if (PARTS_UP_BOOT == (fw_contents & PARTS_UP_BOOT)) #endif { ubootNoUpgrade = 1; } else { UPGRADE_DEBUG("SLP_EFWNOTSUPPORTED"); return SLP_EFWNOTSUPPORTED; } } /* check if kernel and romfs has changes */ if (0 == memcmp(tp_head->firmware_crc, origin_info->kernel_and_romfs_crc, CRC_LEN)) { if (OK != chk_fw_md5_conflict(KERNEL, (U8*)tp_head + origin_info->tphead_len, &conflict)) { UPGRADE_ERROR("Read kernel and romfs partition Exception."); return SLP_EFWEXCEPTION; } else { if (1 == conflict) { kern_and_romfs_changed = 1; UPGRADE_DEBUG("kernel and romfs are changed."); } else { kern_and_romfs_changed = 0; UPGRADE_DEBUG("kernel and romfs are not changed."); } } } else { kern_and_romfs_changed = 1; UPGRADE_DEBUG("kernel and romfs are changed"); } if (0 == access("/tmp/recovery_mode", F_OK)) { kern_and_romfs_changed = 1; } /* check if bootloader has changes */ if (0 == memcmp(tp_head->uboot_crc, origin_info->bootloader_crc, CRC_LEN)) { if (OK != chk_fw_md5_conflict(NORMAL_BOOT, (U8*)up_head + uhTagLength + origin_info->fdt_len, &conflict)) { UPGRADE_ERROR("Read boot partition Exception."); return SLP_ESYSTEM; } else { if (1 == conflict) { boot_changed = 1; UPGRADE_DEBUG("bootloader is changed."); } else { boot_changed = 0; UPGRADE_DEBUG("bootloader is not changed."); } } } else { boot_changed = 1; UPGRADE_DEBUG("bootloader is changed."); } #ifdef FDT_UPGRADE_SUPPORT /* check if fdt has changes */ if (0 == memcmp(tp_head->fdt_crc, origin_info->fdt_crc, CRC_LEN)) { if (OK != chk_fw_md5_conflict(FDT, (U8*)up_head + uhTagLength, &conflict)) { UPGRADE_ERROR("Read fdt partition Exception."); return SLP_ESYSTEM; } else { if (1 == conflict) { fdt_changed = 1; UPGRADE_DEBUG("fdt is changed."); } else { fdt_changed = 0; UPGRADE_DEBUG("fdt is not changed."); } } } else { fdt_changed = 1; UPGRADE_DEBUG("fdt is changed."); } #endif /* 共用固件时,存在只更新ISP参数,不更新软件的情况 */ /* firmware contents are not changed */ /* this should not happen since we have the different FwID and FwID caled from these contents */ if (!kern_and_romfs_changed && !boot_changed && !fdt_changed) { UPGRADE_ERROR("firmware contents are changed."); return SLP_EFWNEWEST; } return SLP_ENONE; } /* 检查 extFw */ LOCAL S32 chk_blocks(unsigned short contentTypes, TP_HEAD_INFO *tp_head, ORIGIN_FW_INFO *origin_info) //检查 extFw { S32 up_contents_changed = boot_changed | kern_and_romfs_changed; S32 i = 0; S32 ret = 0; U32 up_contents = 0x0; /* parts need to be upgraded */ U16 handler_found = 0; BLOCK_HEADER* block_hdr = NULL; up_contents = ntohs(contentTypes); #ifdef CONFIG_TP_TAPO_SPMINIOS if (ntohl(tp_head->jffs2RealFsLen) > 0) { block_hdr = (BLOCK_HEADER*)((U8*)tp_head + ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len) + ntohl(tp_head->jffs2RealFsLen)); } else { block_hdr = (BLOCK_HEADER*)((U8*)tp_head + ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len) + ntohl(tp_head->jffs2_len)); } #ifdef SLP_CAMERA_SUPPORT /*SLP固件结构jffs2结束和ext fw block之间会多保留一个verify分区大小,与tpheader len一致*/ block_hdr = (BLOCK_HEADER*)((U8*)block_hdr + ntohl(tp_head->tphead_len)); #endif #else /* 由于现在去掉了 jffs2,因此 extFw 位于 jffs2 的开始 */ block_hdr = (BLOCK_HEADER*)((U8*)tp_head + ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len)); #endif if (0 != memcmp(g_blk_hdr_magic_num, block_hdr->magic_num, BLOCK_MAGIC_NUMBER_LEN)) { UPGRADE_ERROR("invalid ext_fw block header."); return SLP_EFWEXCEPTION; } for (i = 0; i < sizeof(blk_hdr_tbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++) { /* 当前 extFw 只有 ispconfig */ if (0 != (blk_hdr_tbl[i].type & up_contents)) { handler_found |= blk_hdr_tbl[i].type; ret = blk_hdr_tbl[i].chk_ext_fw(block_hdr, &(blk_hdr_tbl[i]), origin_info); if (ret) { UPGRADE_ERROR("check ext_fw failed, type:0x%x", blk_hdr_tbl[i].type); return SLP_ESYSTEM; } up_contents_changed |= blk_hdr_tbl[i].need_upgrade; } } /* 检查是否为 up_boot 类型 */ if (handler_found != (up_contents & ~(PARTS_UP_BOOT))) { UPGRADE_DEBUG("ERR_SLP_HANDLER_NOT_FOUND"); return SLP_ESYSTEM; } if (!up_contents_changed) { UPGRADE_DEBUG("SLP_EFWNEWEST"); return SLP_EFWNEWEST; } return SLP_ENONE; } #ifdef MAKEROOM_BEFORE_UPGRADE S32 precheck_firmware_required_size(CONTEXT *context) //固件预检查阶段的最小长度 { if (NULL == context) { UPGRADE_DEBUG("Para is null."); return ERROR; } context->precheck_len = sizeof(UPGRADE_HEAD); return SLP_ENONE; } /****************************************************************************** * FUNCTION : check_RSA_version() * AUTHOR : Wu Weizhen (wuweizheng@tp-link.com.cn) * DESCRIPTION : check signature protocol: RSA1024 or RSA2048 * INPUT : the pointer of upgrade_header structure * * OUTPUT : rsaSignatureProtocol: 1:RSA1024, 2:RSA2048 * RETURN : N/A * OTHERS : ******************************************************************************/ static void check_RSA_version(U8* buf) //检查是RSA1024还是RSA2048 { if(NULL == buf) { return; } uint32_t data = 0; uint8_t a; int i; for (i = 0; i < 4; i++) { a = buf[i]; data |= (a << (3-i)*8); } if (data == UPGRADE_HEADER_VERSION_2048) { rsaSignatureProtocol = 2; } else { rsaSignatureProtocol = 1; } } S32 precheck_firmware(CONTEXT *context) //在固件升级流程中进行预检查,验证固件的基本合法性,包括版本、签名协议、魔数、硬件兼容性等信息 { char *buf_start = NULL; S32 buf_len = 0; S32 ret = 0; ORIGIN_FW_INFO origin_info; if (NULL == context || NULL == context->content_start || NULL == context->content_end) { UPGRADE_DEBUG("Para is null."); return ERROR; } buf_start = context->content_start; check_RSA_version((U8*)context->content_start); buf_len = context->content_end - context->content_start; if (buf_len < HEAD_SIZE || memcmp(UP_HEADER_ELE(magic_num), upgrade_header_magic, MAGIC_LEN) != 0) { UPGRADE_DEBUG("Wrong Upgrade Firmware."); return ERROR; } if(rsaSignatureProtocol == 1) //RSA2048未解密,无法解析,RSA1024则保留 { if (buf_len < sizeof(UPGRADE_HEAD) || memcmp(UP_HEADER_ELE(magic_num), upgrade_header_magic, MAGIC_LEN) != 0) { UPGRADE_DEBUG("Wrong Upgrade Firmware."); return ERROR; } /* 本地 firmware 信息初始化 */ ret = origin_info_init(&origin_info); if (SLP_ENONE != ret) { UPGRADE_DEBUG("origin_info_init failed."); return ret; } /* check if HwID in firmware support HwID list */ if (OK != chk_fw_hw_list(UP_HEADER_ELE(hw_id_num), UP_HEADER_ELE(hw_id_list), &origin_info)) { UPGRADE_DEBUG("Not supported HwID."); return SLP_EFWHWIDNOTMATCH; } /* check vendor ID */ if (origin_info.vendor_id != ntohs(UP_HEADER_ELE(vendor_id))) { UPGRADE_DEBUG("firmware vendor_id is 0x%08x and our vendor_id is 0x%08x.", ntohs(UP_HEADER_ELE(vendor_id)), origin_info.vendor_id); return SLP_EFWVENDORIDNOTMATCH; } /* check zone code */ if (origin_info.zone_code != ntohs(UP_HEADER_ELE(zone_code))) { UPGRADE_DEBUG("firmware zone_code is 0x%08x and our zone_code is 0x%08x.", ntohs(UP_HEADER_ELE(zone_code)), origin_info.zone_code); return SLP_EFWZONECODENOTMATCH; } UPGRADE_DEBUG("firmware precheck finished, ok to makeroom before upgrade."); } return SLP_ENONE; } #endif S32 set_fw_rsa_checking(JSON_OBJPTR obj, JSON_OBJPTR* resp_obj) //启用或禁用固件的 RSA 签名验证功能 { const char *enable; if (NULL == (enable = jso_obj_get_string_origin(obj, "enable"))) { printf("Usage:\n" "upgrade set_fw_rsa_checking '{\"enable\": \"off\"}' Disable firmware RSA checking\n" "upgrade set_fw_rsa_checking '{\"enable\": \"on\"}' Enable firmware RSA checking\n" ); return SLP_EINVARG; } if ((!strcmp(enable,"on")) && !g_fw_rsa_checking) { g_fw_rsa_checking = TRUE; UPGRADE_WARNING("Enable firmware RSA checking."); } else if ((!strcmp(enable,"off")) && g_fw_rsa_checking) { g_fw_rsa_checking = FALSE; UPGRADE_WARNING("Disable firmware RSA checking."); } return OK; } /* 固件检查:RSA 签名认证,HwID,vendorID,zoneCode,FwID是否相同,FwIDFL,FwIDBL,partition,ExtFw */ /** * 检查接收的 firmware * * @para: buf_start, 升级固件在内存中的首地址; buf_start, 升级固件的长度; origin_info, 保存本地 firmware 信息的结构体 * * Return: OK/ERROR, 初始化成功/失败 */ S32 check_firmware(U8 *buf_start, U32 buf_len, ORIGIN_FW_INFO *origin_info, S32 bOnlyCheck) //固件检查 { S32 ret; TP_HEAD_INFO *tp_head = NULL; if (buf_len < HEAD_SIZE|| memcmp(UP_HEADER_ELE(magic_num), upgrade_header_magic, MAGIC_LEN) != 0) { UPGRADE_ERROR("Wrong Upgrade Firmware."); return ERROR; } check_RSA_version(buf_start); /* 从更新固件读取 TP HEAD */ /* get firmware's upgrade header length and get it's tp header */ uhTagLength = ntohs(UP_HEADER_ELE(tag_len)); tp_head = (TP_HEAD_INFO*)(buf_start + uhTagLength + origin_info->fdt_len + origin_info->uboot_len); /* check rsa signiture if needed */ /* Now only the domestic version need to check RSA signature */ /* All language will need to chcek RSA */ /*if (0 == strcmp(localInfo.language, LANGUAGE_CN))*/ if (rsaSignatureProtocol == 2) { ret = checkFirmwareRSA_2048((UPGRADE_HEADER_RSA2048 *)buf_start, buf_len, bOnlyCheck, align_size); } else { ret = chk_fw_rsa((UPGRADE_HEAD *)buf_start, buf_len); } if (ret & g_fw_rsa_checking) { UPGRADE_ERROR("RSA%s check error.", rsaSignatureProtocol == 2 ? "2048" : "1024"); return ret; } /* check if HwID in firmware support HwID list */ if (OK != chk_fw_hw_list(UP_HEADER_ELE(hw_id_num), UP_HEADER_ELE(hw_id_list), origin_info)) { UPGRADE_ERROR("Not supported HwID."); return SLP_EFWHWIDNOTMATCH; } /* check vendor ID */ if (origin_info->vendor_id != ntohs(UP_HEADER_ELE(vendor_id))) { UPGRADE_ERROR("firmware vendor_id is 0x%08x and our vendor_id is 0x%08x.", ntohs(UP_HEADER_ELE(vendor_id)), origin_info->vendor_id); return SLP_EFWVENDORIDNOTMATCH; } /* check zone code */ if (origin_info->zone_code != ntohs(UP_HEADER_ELE(zone_code))) { UPGRADE_ERROR("firmware zone_code is 0x%08x and our zone_code is 0x%08x.", ntohs(UP_HEADER_ELE(zone_code)), origin_info->zone_code); return SLP_EFWZONECODENOTMATCH; } /* check if FwID is the same */ if (0 != access("/tmp/recovery_mode", F_OK)) { if (0 == memcmp(origin_info->fw_id, tp_head->fw_id, FW_ID_LEN)) { UPGRADE_DEBUG("FwID is the same."); #ifdef CONFIG_LTE_MODULE_IN_UP_BIN if (origin_info->lte_supported) { goto CHECK_BLOCKS; } #endif return SLP_EFWNEWEST; } } #ifdef CONFIG_SYSUPGRADE_CHECK_FWLIST /* check FL and BL */ if (OK != chk_fw_fl(UP_HEADER_ELE(hw_id_num), UP_HEADER_ELE(hw_id_list), UP_HEADER_ELE(fw_id_fl_num), UP_HEADER_ELE(fw_id_fl_mask), origin_info) \ && OK != chk_fw_bl(tp_head, origin_info)) { return SLP_EFWNOTINFLANDBL; } #endif /* check firmware partitions are enough and if contents are changed */ ret = chk_fw_partition((char *)buf_start, UP_HEADER_ELE(content_types),tp_head, origin_info); if (SLP_ENONE != ret) { return ret; } #ifdef CONFIG_LTE_MODULE_IN_UP_BIN CHECK_BLOCKS: #endif if (!bOnlyCheck || rsaSignatureProtocol != 2) { ret = chk_blocks(UP_HEADER_ELE(content_types), tp_head, origin_info); if (SLP_ENONE != ret) { return ret; } } UPGRADE_ERROR("firmware check finished, ok to upgrade."); return SLP_ENONE; } S32 fw_check_before_upgrade(U8 *content_start, S32 content_len) //对固件进行只读校验,封装了 check_firmware 的调用 { S32 ret = 0; ORIGIN_FW_INFO origin_info; S32 bOnlyCheck = 1; void *upgrade_header_bak = 0; /* restore upgrade header from buf after checking */ if (NULL == content_start || content_len <= 0) { UPGRADE_ERROR("invalid para, content_start[%p], content_len[%d]", content_start, content_len); return SLP_ESYSTEM; } check_RSA_version(content_start); //////////////////////////好像有点多余 /* 本地 firmware 信息初始化 */ ret = origin_info_init(&origin_info); if (SLP_ENONE != ret) { return ret; } align_size = ntohs(((UPGRADE_HEADER_RSA2048*)content_start)->tag_len) + origin_info.uboot_len + sizeof(TP_HEAD_INFO); if(bOnlyCheck) { upgrade_header_bak = malloc(align_size); memcpy(upgrade_header_bak, content_start, align_size); } ret = check_firmware(content_start, content_len, &origin_info, bOnlyCheck); if(bOnlyCheck) { memcpy(content_start, upgrade_header_bak, align_size); free(upgrade_header_bak); upgrade_header_bak = 0; } return ret; } #ifdef CONFIG_TAPO_NAND_UPGRADE LOCAL inline S32 tapo_nandflash_upgrade(U8* fw_base, TP_HEAD_INFO* tp_head, U32 up_contents, ORIGIN_FW_INFO *origin_info) { #define UPBOOT_RESERVED_BLOCK_NUM (6) /* 升级头的定义, 需和factory_boot和uboot中tapo_nand_upgrade.c文件中一样 */ #define UP_BOOT_MAGIC "nand_upboot.bin" #define UPBOOT_INFO_RSV_LEN 202 typedef struct _UPBOOT_INFO { char magic[16]; char md5[16]; int fwLen; int fwStatus; int up_contents; int reserved_block; /* UPBOOT_INFO和UPBOOT_CONTENT之间的块数 */ char mac[6]; /* 用于uboot中isp升级判断 */ char reserve[UPBOOT_INFO_RSV_LEN]; } UPBOOT_INFO; S32 ret = SLP_ENONE; UPBOOT_INFO upgrade_info = {0}; int fwLen = ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len); UPGRADE_ERROR("uboot + tphead + kernel + romfs = %08x", fwLen); fwLen = g_upgrade_param.buf_len - (g_upgrade_param.fw_base - (U8 *)g_upgrade_param.buf); UPGRADE_ERROR("Whole firmware(including isp) = %08x", fwLen); strncpy(upgrade_info.magic, UP_BOOT_MAGIC, sizeof(upgrade_info.magic)); upgrade_info.fwLen = ntohl(fwLen); calc_md5(fw_base, fwLen, (U8 *)upgrade_info.md5); upgrade_info.fwStatus = 0; upgrade_info.up_contents = ntohl(up_contents); upgrade_info.reserved_block = ntohl(UPBOOT_RESERVED_BLOCK_NUM); memcpy(upgrade_info.mac, origin_info->mac, MAC_ADDR_SIZE); ret = flash_write_upboot_content(fw_base, fwLen); if (OK != ret) { return ret; } /* up_boot内容写完之后再写UPBOOT_INFO头 */ ret = flash_write_upboot_header((U8 *)&upgrade_info, sizeof(UPBOOT_INFO)); return ret; } #endif /* ------------------------------------------------Firmware 升级相关函数--------------------------------------*/ /* execute different upgrade process according to upgrade contents. */ // fw_base: 固件数据在内存中的起始地址; // tp_head: 指向 TP_HEAD(固件内容描述头)的指针; // up_contents: 表示要升级的内容类型(如 bootloader、kernel、romfs 等); // origin_info: 当前设备原始固件信息(用于 CRC 校验等); LOCAL S32 execute_upgrade(U8* fw_base, TP_HEAD_INFO* tp_head, U32 up_contents, ORIGIN_FW_INFO *origin_info) //根据升级内容执行不同的升级过程 { S32 ret = SLP_ENONE; UPGRADE_STATUS upgrade_status = { 0 }; UPGRADE_PROCESS is_upgrading = { 0 }; /* 此处需要在 idleworker 线程执行升级前睡眠500ms,以确保web页面已经获得下载成功的回复 */ usleep(500000); /* 开始写flash,升级标志位置1 */ if (ds_read(UPGRADE_STATUS_PATH, &upgrade_status, sizeof(UPGRADE_STATUS)) == 0 || upgrade_status.status) // 读取升级状态文件 UPGRADE_STATUS_PATH 的内容,并判断当前是否已有升级操作正在进行。如果读取失败或当前状态为“升级中”,则返回错误,防止并发升级。 { UPGRADE_ERROR("ds read %s fail", UPGRADE_STATUS_PATH); return ERROR; } /* 下载升级固件前将/upgrade/status置为升级中状态 */ upgrade_status.status = 1; ds_advanced_write(UPGRADE_STATUS_PATH, &upgrade_status, sizeof(UPGRADE_STATUS), DS_FLAG_NOTIFY); UPGRADE_ERROR("execute upgrade... start writing flash"); #ifdef CONFIG_TAPO_NAND_UPGRADE //若启用 NAND Flash 升级方式,调用专用函数;否则执行标准 Flash 分区写入逻辑。 ret = tapo_nandflash_upgrade(fw_base, tp_head, up_contents, origin_info); if (OK != ret) { UPGRADE_ERROR("nandflash upgrad fail"); goto out; } #else S32 i = 0; if (ntohl(tp_head->tphead_offset) == origin_info->tphead_offset) { #ifdef CONFIG_LTE_MODULE_IN_UP_BIN /* upgrade lte fw first */ for (i = 0; i < sizeof(blk_hdr_tbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++) // 遍历扩展固件块表 blk_hdr_tbl,查找类型为 LTE 固件(CONTENT_TYPE_LTE_FW)且需要升级的模块,并执行升级操作 { if (blk_hdr_tbl[i].need_upgrade && blk_hdr_tbl[i].type == CONTENT_TYPE_LTE_FW) { ret = blk_hdr_tbl[i].upgrade_ext_fw(blk_hdr_tbl[i].block); if (SLP_ENONE != ret) { UPGRADE_ERROR("upgrade lte fw failed, type:0x%x", blk_hdr_tbl[i].type); goto out; } blk_hdr_tbl[i].need_upgrade = EXT_FW_NOT_CHANGED; } } #endif /* 更新 extFw */ for (i = 0; i < sizeof(blk_hdr_tbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++) //遍历所有需要升级的扩展模块并执行升级 { if (blk_hdr_tbl[i].need_upgrade) { ret = blk_hdr_tbl[i].upgrade_ext_fw(blk_hdr_tbl[i].block); if (SLP_ENONE != ret) { UPGRADE_ERROR("upgrade ext_fw failed, type:0x%x", blk_hdr_tbl[i].type); goto out; } } } if (NULL == tp_head->factory_info_crc || NULL == tp_head->radio_crc) { UPGRADE_ERROR("NULL TP HEAD CRC"); ret = SLP_EFWEXCEPTION; goto out; } memcpy(tp_head->factory_info_crc, origin_info->factory_info_crc, CRC_LEN); memcpy(tp_head->radio_crc, origin_info->radio_crc, CRC_LEN); } #ifdef CONFIG_TP_TAPO_MAP_ROOTFS UPGRADE_DEBUG("map rootfs ..."); flash_rootfs_map(); #endif int fdt_len = 0; #ifdef FDT_UPGRADE_SUPPORT fdt_len = ntohl(tp_head->fdt_len); #endif /* 写入 bootloader */ if ((up_contents & CONTENT_TYPE_BOOTLOADER) && (1 != ubootNoUpgrade)) { ret = flash_write_boot(fw_base + fdt_len, ntohl(tp_head->uboot_len)); if (OK != ret) { UPGRADE_ERROR("write bootloader failed"); goto out; } UPGRADE_ERROR("write bootloader success"); } #ifdef CONFIG_TP_TAPO_SPMINIOS #ifdef SLP_CAMERA_SUPPORT /* SLP固件的分区划分为kernel_len + romfs_len = jffs2_len*/ if (ntohl(tp_head->jffs2_len) < ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len)) #else if (ntohl(tp_head->jffs2_len) < ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len)) #endif { UPGRADE_ERROR("UP format error"); goto out; } ret = flash_write_verify(fw_base + fdt_len + ntohl(tp_head->uboot_len), ntohl(tp_head->tphead_len)); if (OK != ret) { UPGRADE_ERROR("backup tpheader failed"); goto out; } // 如果 jffs2RealFsLen 有值,则写入其指定大小; // 否则写入 jffs2_len 指定大小; // 根据是否启用 SLP_CAMERA_SUPPORT,写入地址不同 if (ntohl(tp_head->jffs2RealFsLen) > 0) { #ifdef SLP_CAMERA_SUPPORT /*SLP固件的flash分区大小只支持将kernel_and_romfs备份至jffs2,不包含tpheader,tpheader由verify分区备份*/ ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len), ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len)); #else ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len), ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len)); #endif } else { ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len), ntohl(tp_head->jffs2_len)); } if (ret != OK) { UPGRADE_ERROR("backup failed"); goto out; } #endif ret = flash_write_tpheader(fw_base + fdt_len + ntohl(tp_head->uboot_len), ntohl(tp_head->tphead_len)); //fdt if (OK != ret) { UPGRADE_ERROR("write tpheader failed"); goto out; } #ifdef FDT_UPGRADE_SUPPORT /* 升级fdt */ if (up_contents & CONTENT_TYPE_FDT) //fdt { ret = flash_write_fdt(fw_base, fdt_len); if (OK != ret) { UPGRADE_ERROR("write fdt failed"); goto out; } UPGRADE_ERROR("write fdt success"); } #endif if ((up_contents & CONTENT_TYPE_KERNEL) && (up_contents & CONTENT_TYPE_ROMFS)) { ret = flash_write_kernel(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len), // fdt ntohl(tp_head->kernel_len)); if (ret != OK) { UPGRADE_ERROR("write kernel failed"); goto out; } ret = flash_write_romfs(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len), ntohl(tp_head->romfs_len)); if (ret != OK) { UPGRADE_ERROR("write romfs failed"); goto out; } UPGRADE_ERROR("write romfs success"); } #ifdef CONFIG_TP_TAPO_SPMINIOS if (ntohl(tp_head->jffs2RealFsLen) > 0) { ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len), ntohl(tp_head->jffs2RealFsLen)); } else { ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len), ntohl(tp_head->jffs2_len)); } if (ret != OK) { UPGRADE_ERROR("write jffs2 failed"); goto out; } #endif #endif /* end CONFIG_TAPO_NAND_UPGRADE */ upgrade_status.lastUpgradingSuccess = 1; out: /* 写flash结束,升级标志位置0 */ upgrade_status.status = 0; is_upgrading.state = 0; ds_write(UPGRADE_PROCESS_PATH, &is_upgrading, sizeof(UPGRADE_PROCESS)); ds_advanced_write(UPGRADE_STATUS_PATH, &upgrade_status, sizeof(UPGRADE_STATUS), DS_FLAG_NOTIFY); return ret; } /* 获取共享内存: 成功返回 共享内存id;失败返回 ERROR */ // p_store_buf:用于返回共享内存的地址; // key:共享内存的唯一标识符; // 返回值:共享内存的 ID(shm_id),失败返回 ERROR。 LOCAL S32 upgrade_get_shm(U8 **p_store_buf, S32 key) //获取共享内存,因为下载的固件保存在共享内存 { void *shm = NULL; S32 shm_id; if (NULL == p_store_buf) { return ERROR; } /* 如果共享内存尚未被其他模块创建,则返回ERROR */ shm_id = shmget((key_t)key, 0, IPC_CREAT|IPC_EXCL); if (-1 != shm_id) { UPGRADE_ERROR("shm[%d] has not been created by other module.(%d, %s)", key, errno, strerror(errno)); return ERROR; } /* 获取共享内存id */ shm_id = shmget((key_t)key, 0, 0660|IPC_CREAT); if (-1 == shm_id) { UPGRADE_ERROR("get shm-id of key[%d] failed.(%d, %s)", key, errno, strerror(errno)); return ERROR; } shm = shmat(shm_id, NULL, 0); //将共享内存段连接到当前进程的地址空间; if ((void*)ERROR == shm) { UPGRADE_ERROR("shmat failed."); return ERROR; } *p_store_buf = shm; return shm_id; } LOCAL S32 upgrade_detach_shm(U8* fw_buf) //解除共享内存 { if (NULL == fw_buf) { UPGRADE_ERROR("invald para"); return ERROR; } UPGRADE_DEBUG("fw_buf[%p]", fw_buf); if (-1 == shmdt((void *) fw_buf)) { UPGRADE_ERROR("shmdt failed", errno, strerror(errno)); return ERROR; } return OK; } LOCAL S32 idleworker_execute_upgrade(void * param) //调用execute_upgrade,使其运行在一个空闲任务(idle worker)线程中 { S32 ret = OK; #ifdef FACTORY_BOOT_SDCARD_RECOVERY /* 进行固件备份,无论成功或失败都继续执行固件升级 */ sd_recovery_save_fw(g_upgrade_param.buf, g_upgrade_param.buf_len); #endif ret = execute_upgrade(g_upgrade_param.fw_base, g_upgrade_param.tp_head, g_upgrade_param.up_contents, &g_upgrade_param.origin_info); if (ret) { UPGRADE_ERROR("execute_upgrade failed, exit"); } return ret; } // 是一个固件升级完成后的回调函数,用于清理升级过程中使用的资源(如共享内存或文件映射), // 并发送升级结果消息通知其他模块。它通常在升级执行完成后调用,确保系统状态更新和资源释放。 LOCAL S32 idleworker_execute_upgrade_callback(S32 ret) { /* 发送消息通知结果 */ EXECUTE_UPGRADE_MSG msg = { 0 }; /* 共享内存升级方式进行一次 shmat 增加一次引用计数,升级结束后需减1 */ if (g_upgrade_param.upgrade_type == EXECUTE_UPGRADE_SHM) { upgrade_detach_shm(g_upgrade_param.buf); } else if (g_upgrade_param.upgrade_type == EXECUTE_UPGRADE_FILE || g_upgrade_param.upgrade_type == EXECUTE_UPGRADE_LOCALFILE) { munmap(g_upgrade_mmap_addr, g_upgrade_file_size); if (g_upgrade_file_fd != -1) { close(g_upgrade_file_fd); } } msg.type = g_upgrade_param.upgrade_type; msg.id = g_upgrade_param.id; msg.ret = ret; NSD_SEND(EXECUTE_UPGRADE_MID, (U8*)&msg, sizeof(EXECUTE_UPGRADE_MSG)); g_upgrade_param.is_upgrading = 0; return OK; } /** * 升级接收的 firmware * * @context: buf,升级固件的缓存 buf_len, 升级固件的长度; origin_info, 保存本地 firmware 信息的结构体 * * Return: OK/ERROR, 升级成功/失败 */ LOCAL S32 do_firmware_upgrade(U8* buf, U32 buf_len, ORIGIN_FW_INFO *origin_info) //确定需要升级的部分,并将实际的升级操作调度到一个空闲任务(idle worker)中执行 { S32 ret = 0; TP_HEAD_INFO* tp_head; UPGRADE_HEAD *up_head; U8* fw_base = 0; U32 up_contents = 0x0; /* parts need to be upgraded */ up_head = (UPGRADE_HEAD*)buf; up_contents = ntohs(up_head->content_types); fw_base = buf + ntohs(up_head->tag_len); tp_head = (TP_HEAD_INFO*)(buf + ntohs(up_head->tag_len) + origin_info->fdt_len + origin_info->uboot_len); /* decide upgrade parts if flash layout not changed */ if (ntohl(tp_head->tphead_offset) == origin_info->tphead_offset) { /* firmware contains bootloader which is not changed */ if (!boot_changed) { up_contents &= ~CONTENT_TYPE_BOOTLOADER; UPGRADE_DEBUG("Bootloader won't be upgraded."); } /* firmware contains kernel and romfs which are not changed */ if (!kern_and_romfs_changed) { up_contents &= ~(CONTENT_TYPE_KERNEL | CONTENT_TYPE_ROMFS); UPGRADE_DEBUG("Kernel and romfs won't be upgraded."); } #ifdef FDT_UPGRADE_SUPPORT /* firmware contains fdt which are not changed */ if (!fdt_changed) //fdt { up_contents &= ~CONTENT_TYPE_FDT; UPGRADE_ERROR("fdt won't be upgraded."); } #endif } g_upgrade_param.buf = buf; g_upgrade_param.buf_len = buf_len; g_upgrade_param.fw_base = g_upgrade_param.buf + (fw_base - buf); g_upgrade_param.tp_head = g_upgrade_param.buf + ((U8 *)tp_head - buf); g_upgrade_param.up_contents = up_contents; memcpy(&g_upgrade_param.origin_info, origin_info, sizeof(ORIGIN_FW_INFO)); /* 将耗时的execut_upgrade函数放到idleworker中完成 */ ret = iw_add_worker(idleworker_execute_upgrade, NULL, 0, idleworker_execute_upgrade_callback); if (ERROR == ret) { UPGRADE_ERROR("add idle worker failed."); ret = SLP_EFWEXCEPTION; goto error_out; } UPGRADE_ERROR("add job to idleworker success"); return SLP_ENONE; error_out: return ret; } /****************************************/ #define REBOOT_DELAY_SECOND 1 /* 延时重启 */ LOCAL void system_reboot_delay(S32 data) { reboot(RB_AUTOBOOT); } S32 reboot_delay() { if (inet_add_timer(system_reboot_delay, 0, REBOOT_DELAY_SECOND, EXECUTE_SINGLE) == -1) { return ERROR; } return OK; } LOCAL U32 red_led_gpio = 0; LOCAL U32 green_led_gpio = 0; LOCAL void upgrading_led() { LED_STATE_MSG led_msg; memset(&led_msg, 0, sizeof(led_msg)); led_msg.state = LED_STATE_FW_UPGRADING; NSD_SEND(LED_STATE_MID, (U8 *)&led_msg, sizeof(led_msg)); } void upgrade_success_led() { LED_STATE_MSG led_msg; memset(&led_msg, 0, sizeof(led_msg)); led_msg.state = LED_STATE_FW_UPGRADE_SUC; NSD_SEND(LED_STATE_MID, (U8 *)&led_msg, sizeof(led_msg)); } void upgrade_fail_led() { LED_STATE_MSG led_msg; memset(&led_msg, 0, sizeof(led_msg)); led_msg.state = LED_STATE_FW_UPGRADE_FAIL; NSD_SEND(LED_STATE_MID, (U8 *)&led_msg, sizeof(led_msg)); } LOCAL void upgrade_check_fail_led() { LED_STATE_MSG led_msg; memset(&led_msg, 0, sizeof(led_msg)); led_msg.state = LED_STATE_FW_CHECK_FAIL; NSD_SEND(LED_STATE_MID, (U8 *)&led_msg, sizeof(led_msg)); } void led_init() { GPIO_CFG gpio; memset(&gpio, 0, sizeof(gpio)); ds_read(GPIO_CFG_PATH, &gpio, sizeof(gpio)); red_led_gpio = gpio.red_led_gpio; green_led_gpio = gpio.green_led_gpio; } LOCAL S32 firmware_upgrade_core(U8 *content_start, S32 content_len) //调用检查和升级函数以及一些led指示灯函数实现升级流程 { ORIGIN_FW_INFO origin_info; S32 ret = 0; CLIENT_INFO client_info; S32 bOnlyCheck = 0; //执行升级操作,不只检查文件签名 if (NULL == content_start || content_len <= 0) { UPGRADE_ERROR("invalid para, content_start[%p], content_len[%d]", content_start, content_len); return SLP_ESYSTEM; } check_RSA_version(content_start); /* 本地 firmware 信息初始化 */ ret = origin_info_init(&origin_info); if (SLP_ENONE != ret) { UPGRADE_ERROR("init origin info fail"); goto FW_ERROR; } memset(&client_info, 0, sizeof(CLIENT_INFO)); ds_read(CLOUD_STATUS_CLIENT_INFO_PATH, &client_info, sizeof(CLIENT_INFO)); /* 检查固件 */ ret = check_firmware(content_start, content_len, &origin_info, bOnlyCheck); if (SLP_ENONE != ret) { upgrade_check_fail_led(); if (DOWNLOAD_FW_SUCCESS == client_info.fw_download_status) { client_info.fw_verify_status = VERIFY_STAT_FAIL; ds_write(CLOUD_STATUS_CLIENT_INFO_PATH, &client_info, sizeof(CLIENT_INFO)); } UPGRADE_ERROR("check firmware erro"); goto FW_ERROR; } if (DOWNLOAD_FW_SUCCESS == client_info.fw_download_status) { client_info.fw_verify_status = VERIFY_STAT_SUCCESS; ds_write(CLOUD_STATUS_CLIENT_INFO_PATH, &client_info, sizeof(CLIENT_INFO)); } upgrading_led(); /* 进行固件升级 */ ret = do_firmware_upgrade(content_start, content_len, &origin_info); if (ret) { UPGRADE_ERROR("upgrade firmware failed"); upgrade_fail_led(); goto FW_ERROR; } /* 升级结果应该在各源头的消息接收函数中处理,下不应有代码 */ UPGRADE_DEBUG("upgrade firmware over"); return SLP_ENONE; FW_ERROR: return ret; } LOCAL S32 fw_file_upgrade(char *path) //文件路径中读取固件并升级 { int ret = 0; struct stat sb; if (path == NULL) { UPGRADE_ERROR("path empty"); return SLP_ESYSTEM; } ds_stop_module_for_upgrade(); g_upgrade_file_fd = open(path, O_RDONLY); if (g_upgrade_file_fd < 0) { UPGRADE_ERROR("cannot open file path"); return SLP_ESYSTEM; } /* 获取文件大小 */ if (fstat(g_upgrade_file_fd, &sb) < 0) { UPGRADE_ERROR("get file size error"); goto ERROR_OUT; } g_upgrade_file_size = sb.st_size; UPGRADE_ERROR("file size: %d", g_upgrade_file_size); g_upgrade_mmap_addr = mmap(NULL, g_upgrade_file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_upgrade_file_fd, 0); if (g_upgrade_mmap_addr == MAP_FAILED) { UPGRADE_ERROR("mmap error"); goto ERROR_OUT; } ret = firmware_upgrade_core((U8 *)g_upgrade_mmap_addr, g_upgrade_file_size); if (OK != ret) { UPGRADE_ERROR("firmware_upgrade add idleworker failed"); munmap(g_upgrade_mmap_addr, g_upgrade_file_size); goto ERROR_OUT; } return OK; ERROR_OUT: if (g_upgrade_file_fd != -1) { close(g_upgrade_file_fd); } return ERROR; } LOCAL S32 upgrade_file_method(UPGRADE_MSG *msg) { return fw_file_upgrade(msg->u.file_path); } LOCAL S32 upgrade_shm_method(UPGRADE_MSG *msg) //共享内存中读取固件并升级 { S32 ret = 0; S32 shm_id = 0; U8* shm_fw_buf = NULL; shm_id = upgrade_get_shm(&shm_fw_buf, msg->u.shm_key); if (ERROR == shm_id) { UPGRADE_ERROR("fw_get_shm fail"); return SLP_ESYSTEM; } /* 调用固件升级函数 */ ret = firmware_upgrade_core(shm_fw_buf, msg->fw_len); /* 升级不成功,任务未传递给 idleworker ,引用计数需减1 */ if (ret != OK) { upgrade_detach_shm(shm_fw_buf); } return ret; } LOCAL S32 upgrade_mem_method(UPGRADE_MSG *msg) { return firmware_upgrade_core(msg->u.addr, msg->fw_len); } LOCAL UPGRADE_METHOD g_upgrade_method_list[] = { {EXECUTE_UPGRADE_FILE, upgrade_file_method}, {EXECUTE_UPGRADE_SHM, upgrade_shm_method}, {EXECUTE_UPGRADE_MEM, upgrade_mem_method}, {EXECUTE_UPGRADE_LOCALFILE, upgrade_file_method}, }; void fw_upgrade_ready_cb(void *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) //根据三种方式进行升级 { S32 ret = 0; S32 i = 0; UPGRADE_MSG *msg = NULL; EXECUTE_UPGRADE_MSG exec_msg = { 0 }; UPGRADE_PROCESS is_upgrading = { 0 }; if (NULL == mbuf) { UPGRADE_ERROR("mbuf is null"); ret = SLP_ESYSTEM; goto EXIT; } msg = (UPGRADE_MSG *)mbuf; if (g_upgrade_param.is_upgrading) { UPGRADE_ERROR("other firmware_upgrade is in progress."); return; } lock_text_segments(); g_upgrade_param.is_upgrading = 1; g_upgrade_param.upgrade_type = msg->type; g_upgrade_param.id = msg->id; if (ds_read(UPGRADE_PROCESS_PATH, &is_upgrading, sizeof(UPGRADE_PROCESS)) == 0) { UPGRADE_ERROR("read upgrade_status error."); return; } /* 升级固件前将/upgrade/status/is_upgrading置为升级中状态 */ is_upgrading.state = 1; ds_write(UPGRADE_PROCESS_PATH, &is_upgrading, sizeof(UPGRADE_PROCESS)); UPGRADE_ERROR("upgrade recv message, type: %d, id: %d", msg->type, msg->id); for (i = 0; i < sizeof(g_upgrade_method_list) / sizeof(UPGRADE_METHOD); i++) { if (msg->type == g_upgrade_method_list[i].upgrade_type) { ret = g_upgrade_method_list[i].method(msg); break; } } EXIT: if (OK != ret) { UPGRADE_ERROR("firmware upgrade fail and firmware not changed"); /* 如固件校验失败,由 upgrade 回复升级失败消息,校验成功则由 idleworker 回复消息 */ exec_msg.type = msg->type; exec_msg.id = msg->id; exec_msg.ret = ret; is_upgrading.state = 0; ds_write(UPGRADE_PROCESS_PATH, &is_upgrading, sizeof(UPGRADE_PROCESS)); msg_send(EXECUTE_UPGRADE_MID, (U8 *)&exec_msg, sizeof(EXECUTE_UPGRADE_MSG)); g_upgrade_param.is_upgrading = 0; } return; } 梳理一下这段代码的结构
最新发布
09-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值