一种修复固件代码的方法及系统
技术领域
本申请涉及一种对硬件设备的固件代码进行修复的方法,所述固件代码保存在数据一旦写入就无法更改或删除的非易失性存储器(NVM)中。
背景技术
在电子及计算机领域中,固件(firmware)是指为特定硬件提供底层控制的特定类别的软件。典型的包含固件的硬件设备包括嵌入式设备、家用电器、计算机、计算机外围设备等。固件一般保存在硬件设备的NVM中,通常是芯片内部的NVM中,或者是与芯片封装在一起的NVM中。
有些硬件设备的固件代码一旦写入NVM中就永久保存而无法更改或删除,例如只读存储器(ROM)、熔丝存储器(eFuse)等就有这样的特性常用来写入固件代码。此时,如果发现固件代码有问题也无法对其进行修改,从而使得硬件设备作废。
申请公布号为CN106164860A、申请公布日为2016年11月23日的中国发明专利申请《用于修改初始化计算设备所使用的固件的系统和方法》公开了一种为启动ROM固件打补丁的方法。所述方法可在运行启动ROM固件的执行期间能够替换指令或语句和数据,然而需要采用两种额外的硬件。第一种是SoC系统中的控制器,用来加载指令序列和补丁处理逻辑;第二种是ROM或PROM,用来存储经修改的启动代码和补丁实例等。所述方法采用两种额外的硬件使得成本上升。
发明内容
本申请所要解决的技术问题是提供一种对硬件设备中的固件代码进行修复的方法,所述固件代码保存在硬件设备的非易失性存储器中,所述非易失性存储器具有一旦写入就无法更改的特性。所述修复是指对固件代码中的部分内容进行修改或删除、或在固件代码中新增部分内容。与所述方法相对应地,本申请还公开了一种对硬件设备中的固件代码进行修复的系统。
为解决上述技术问题,本申请提供了一种修复固件代码的方法,包括设置过程,所述设置过程包括如下步骤。
第1-1步:将包含桩子程序在内的固件代码在硬件设备的制造过程中一次性地写入到硬件设备的非易失性存储器一中;所述非易失性存储器一具有数据一旦写入就无法更改或删除的特性。
第1-2步:如果要对原固件代码进行新增、修改或删除,则在硬件设备的非易失性存储器二中写入控制块;每个控制块包括原固件代码中需要新增、修改或删除代码的第一位置、以及该第一位置的补丁代码。
所述桩子程序在硬件设备每次上电后都会进行初始化;桩子程序的初始化是根据每个控制块分别在硬件设备的CPU的寄存器中设置断点,每个断点与每个控制块相对应。
CPU执行原固件代码时,一旦执行到断点位置就跳转执行所述桩子程序,由所述桩子程序执行该断点对应的控制块中的指令和/或数据。
所述修复固件代码的方法的设置过程是在固件代码中预先植入桩子程序,并在非易失性存储器二中以控制块的形式记录需要新增、修改或删除(跳过)的原固件代码的第一位置及其补丁代码。
进一步地,所述第1-1步中,所述桩子程序位于固件代码中的开头位置或靠近开头位置。由于桩子程序是用来对原固件代码进行修复的,将其放置在固件代码的尽可能靠近开头的位置,可以在硬件设备上电后初始化桩子程序,从而最大程序地扩展原固件代码的可修复范围(桩子程序之后的代码)。
进一步地,所述断点包括硬件断点和/或片上断点;所述硬件断点包括读断点、写断点、代码执行断点;所述片上断点也包括读断点、写断点、代码执行断点。本申请所述断点不包括软件断点,这是由于软件断点是对原固件代码直接进行修改,而这是一次写入型的非易失性存储器所不支持的特性。
进一步地,所述第1-2步中,所述补丁代码还包括一旦执行完毕所述补丁代码后跳转到原固件代码中的第二位置的指令。这是为了对原固件代码进行更加灵活的修复或更新。如果不包括该跳转到第二位置的指令,相当于在原固件代码中新增部分代码。如果包括该跳转到第二位置的指令,就可以跳过原固件代码中的部分代码,相当于在原固件代码中修改或删除部分代码。
进一步地,所述修复固件代码的方法还包括执行过程,所述执行过程包括如下步骤。
第2-1步:硬件设备每次上电后,CPU执行原固件代码,对桩子程序进行初始化。
第2-2步:所述桩子程序在初始化时,查看硬件设备的非易失性存储器二中是否存在控制块;如果存在控制块,则把每个控制块中记载的第一位置在硬件设备的CPU的寄存器中分别设置为断点,所设置的断点的数量与控制块的数量相同,并且每个断点与每个控制块相对应;所有的控制块均设置为断点后,CPU继续执行原固件代码;如果不存在控制块,CPU继续执行原固件代码。
第2-3步:CPU继续执行原固件代码时,一旦执行到断点位置即跳转到断点的异常处理向量位置,再跳转执行所述桩子程序。
第2-4步:所述桩子程序根据CPU的寄存器提供的信息来判断由哪一个断点引发了异常处理向量,执行该断点对应的控制块中的补丁代码,在执行完毕后由CPU继续执行原固件代码。
所述修复固件代码的方法的执行过程通过预先植入的桩子程序的初始化及后续运行,并借助硬件设备的CPU的断点机制,使得修复或更新后的固件代码得以被CPU正确地被识别和执行。
进一步地,所述第2-2步中,所述桩子程序根据第一位置的操作类型决定所设置的断点类型;所述操作类型包括读、写、执行;相应的断点类型分别是读断点、写断点、代码执行断点;所述第一位置的操作类型也记载在控制块中。这可以更加灵活地对原固件代码进行修复或更新。
进一步地,所述第2-2步中,CPU支持硬件断点、片上断点的至少一种,并且CPU所支持的最大断点数量大于或等于所述控制块的数量。这是所述修复固件代码的方法的执行过程得以成功实现的前提条件。
与所述修复固件代码的方法相对应地,本申请还提供了一种修复固件代码的系统,包括写入单元和修复单元。
所述写入单元用于将包含桩子程序在内的固件代码在硬件设备的制造过程中一次性地写入到硬件设备的非易失性存储器一中;所述非易失性存储器一具有数据一旦写入就无法更改或删除的特性。
所述修复单元用于在硬件设备的非易失性存储器二中写入控制块。
所述修复固件代码的系统可用来实现所述修复固件代码的方法的设置过程,并与之一一对应。
进一步地,所述修复固件代码的系统还包括CPU、断点设置单元、断点执行单元。
所述CPU用来执行固件代码,一旦执行到桩子程序的位置就由断点设置单元工作,一旦执行到断点位置就由断点执行单元工作。
所述断点设置单元用来根据硬件设备的非易失性存储器二中的每个控制块在硬件设备的CPU的寄存器中分别设置为断点,所设置的断点的数量与控制块的数量相同,并且每个断点与每个控制块相对应;所有的控制块均设置为断点后,所述断点设置单元退出工作,交由硬件设备的CPU继续执行原固件代码。
所述断点执行单元用来根据CPU的寄存器提供的信息寻找断点对应的控制块,并执行所述对应的控制块中的补丁代码,在执行完毕后所述断点执行单元退出工作,交由硬件设备的CPU继续执行原固件代码。
所述修复固件代码的系统可用来实现所述修复固件代码的方法的执行过程,并与之一一对应。
进一步地,每个控制块包括一个控制字段,还包括一个或多个程序和/或数据字段,每个控制块的大小相同或者不同;在程序和/或数据字段中记载有所述补丁代码。这是控制块的一种具体数据结构,仅作为示例。
进一步地,所述控制字段又被分为X、Y、Z三个区域;X区域用来记录原固件代码中需要修改的一处代码位置即第一位置;Y区域用来记录下一个控制块的地址;Z区域用来表示该非易失性存储器二是否为激活。这是控制字段的一种具体数据结构,仅作为示例。
本申请取得的技术效果是:当原固件代码出现缺陷时,本申请可以跳过缺陷部分,而改为执行补丁代码,相当于对原固件代码的缺陷部分进行了修复。当需要为原固件代码增加新内容或新功能时,本申请可以执行新增代码,相当于对原固件代码进行了更新。本申请的修复固件代码的方法及系统利用了CPU内部的断点机制,采用少量额外的非易失性存储器硬件来写入补丁代码,不需要额外的支持启动的硬件设备和技术,降低了成本,提高了可靠性。
附图说明
图1是本申请提供的修复固件代码的方法的设置过程的流程示意图。
图2是本申请提供的修复固件代码的方法的执行过程的流程示意图。
图3是本申请提供的修复固件代码的系统的实施例一的方框结构示意图。
图4是本申请提供的修复固件代码的系统的实施例二的方框结构示意图。
图5是本申请提供的控制块的数据结构示意图。
图6是本申请提供的控制字段的数据结构示意图。
具体实施方式
本申请提供了一种修复固件代码的方法,包括设置过程和执行过程。设置过程是对原固件代码进行新增、修改、删除(跳过)代码的操作,从而实现了对原固件代码的修复或更新。执行过程是硬件设备的CPU正确地识别并执行修复或更新后的固件代码的过程。
请参阅图1,本申请提供的修复固件代码的方法的设置过程包括如下步骤。
第1-1步S11:将包含桩子(stub)程序在内的固件代码在硬件设备的制造过程中一次性地写入到硬件设备的非易失性存储器一中。所述非易失性存储器一具有数据一旦写入就无法更改或删除的特性,例如采用ROM、eFuse等。
所述桩子程序在硬件设备每次上电后都会进行初始化,并在初始化完毕后继续执行原固件代码。桩子程序的初始化是根据每个控制块分别在硬件设备的CPU的寄存器中设置断点(breakpoint),每个断点与每个控制块相对应。所述设置断点包括硬件断点(hardware breakpoint)和/或片上断点(onchip breakpoint)。硬件断点包括读断点、写断点、代码执行断点三种。片上断点也包括读断点、写断点、代码执行断点三种。读断点是指CPU读取某个地址时进入异常处理向量(Vector)。写断点是指CPU向某个地址写入时进入异常处理向量。代码执行断点是指CPU执行某个地址的代码时进入异常处理向量。
CPU执行原固件代码时,一旦执行到断点位置都会跳转到断点的异常处理向量。在异常处理向量位置通常设置一条跳转到桩子程序的指令,因此原固件代码每次运行到断点位置时会跳转执行桩子程序。此时由桩子程序执行该断点对应的控制块中的指令和/或数据,并在执行完毕后继续执行原固件代码。
所述桩子程序作为固件代码的一部分。优选地,所述桩子程序位于固件代码中尽可能靠近开头的位置,以使硬件设备在上电后能够尽早地进行桩子程序的初始化。同时,桩子程序之前的代码和/或数据较少,出错的概率也随之降低,这样可以为桩子程序之后的代码和/或数据提供修复的机会。
第1-2步S12:如果要对原固件代码进行新增、修改或删除,则在硬件设备的非易失性存储器二中写入控制块。所述非易失性存储器二可以采用可以反复擦写的存储器,例如采用EPROM(可擦除可编程只读存储器)、EEPROM(电可擦除可编程只读存储器)、NOR型或NAND型闪存(flash)、安全数字卡(SD Card,Secure Digital Memory Card)等。所述控制块是指一段代码,包括指令和/或数据。每个控制块都至少包括原固件代码中需要新增、修改或删除代码的第一位置、以及该第一位置的补丁代码。所述补丁代码中包括指令,还可能包括有这些指令所要操作的数据,还可能包括一旦执行完毕所述补丁代码后跳转到原固件代码中的第二位置的指令。如果补丁代码中没有跳转到第二位置的指令,那么桩子程序执行完毕所述补丁代码后,回到原固件代码中的第一位置继续进行读、写或执行操作(视断点类型而定)。
如果第二位置是第一位置在原固件代码中紧邻在后的一条代码,就表明是在原固件代码中新增内容。
如果第二位置与第一位置在原固件代码中相距一条以上代码(即不是紧邻关系),就可以用来舍弃原固件代码中的从第一位置到第二位置之间的部分代码,不含两端点;改为执行补丁代码,这相当于对原固件代码的部分内容的修改或删除(跳过)。考虑到代码语句之间可能存在跳转,上述舍弃部分代码的描述只是一种可能的用途。
通过巧妙地设计第一位置与第二位置,就可在原固件代码中新增内容、或者对原固件代码中的部分内容进行修改或删除(跳过),这样就实现了对原固件代码的修复或更新。
上述设置过程在固件代码中预先植入了桩子程序,桩子程序是后续执行过程中硬件设备的CPU能够正确执行修复或更新后的固件代码的关键所在,也是现有的固件代码中未曾包含的内容,体现了本申请的创新所在。
请参阅图2,本申请提供的修复固件代码的方法的执行过程包括如下步骤。
第2-1步S21:硬件设备每次上电后,硬件设备的CPU执行非易失性存储器一中的原固件代码,对桩子程序进行初始化。例如是在正常执行原固件代码并且首次执行到桩子程序的位置时对其进行初始化。
第2-2步S22:所述桩子程序在初始化时,查看硬件设备的非易失性存储器二中是否存在控制块。如果存在控制块,根据每个控制块中记载的第一位置分别在硬件设备的CPU的寄存器中设置为断点,所设置的断点的数量与控制块的数量相同,并且每个断点与每个控制块相对应。所有的控制块均设置为断点后,桩子程序完成初始化,CPU执行原固件代码中桩子程序的下一条代码。如果不存在控制块,则CPU执行原固件代码中桩子程序的下一条代码。
设置断点时,可以根据第一位置的操作类型决定断点类型。如果需要在第一位置读取时运行补丁代码,则可设置为读断点。如果需要在第一位置写入时运行补丁代码,则可设置为写断点。如果需要在第一位置执行时运行补丁代码,则可设置为代码执行断点。第一位置的操作类型也可记载在控制块中。
设置断点时有两个前提条件默认为是满足的。第一是硬件设备的CPU必须支持硬件断点和/或片上断点。CPU读、写、或执行到断点位置就会触发CPU跳转进入异常处理向量,所述异常处理向量是指CPU响应异常处理(exception)跳转的地址。这在CPU的调试逻辑中是很常见的功能,一般都能满足。第二是硬件设备的CPU所支持的最大断点数量必须大于或等于所述非易失性存储器二中的控制块的数量。换而言之,本申请所支持的补丁代码的数量必须小于或等于硬件设备的CPU所支持的最大断点数量。
第2-3步S23:硬件设备的CPU在继续执行原固件代码时,一旦发现执行到断点位置即跳转到异常处理向量,再跳转执行所述桩子程序。
第2-4步S24:所述桩子程序根据CPU的寄存器提供的信息判断由哪一个断点引发异常处理向量,执行该断点对应的控制块中的补丁代码,在执行完毕后由CPU继续执行原固件代码。如果所述补丁代码中包括跳转到第二位置的指令,那么在执行完毕所述补丁代码后由CPU跳转到原固件代码的第二位置继续执行。如果所述补丁代码中没有跳转到第二位置的指令,那么在执行完毕所述补丁代码后回到原固件代码中的第一位置继续进行读、写或执行操作(视断点类型而定)。
上述执行过程通过预先植入的桩子程序的初始化及后续运行,并借助硬件设备的CPU的断点机制,使得修复或更新后的固件代码得以被CPU正确地被识别和执行。
以ARM架构的CPU为例,用来设置断点的例如是CPU的调试寄存器(debugregister)或是其他的断点寄存器。本申请提供的修复固件代码的方法的执行过程可以作如下描述。首先,硬件设备上电,CPU开始执行原固件代码直至首次到达桩子程序。然后,桩子程序初始化,先去读取非易失性存储器二判断是否存在控制块。如果存在控制块,桩子程序就根据每个控制块中记录的第一位置及其操作类型在CPU的异常向量表中分别设置断点,例如为硬件断点和/或片上断点,并且使能(enable)异常调试(Debug Exception)功能。所述异常调试功能被使能后,CPU执行到断点就会跳转到异常向量表的异常入口位置,该异常入口位置就指向桩子程序。随后桩子程序退出,CPU正常执行原固件代码。如果不存在控制块,则桩子程序退出,CPU正常执行原固件代码。再后,当CPU执行到断点位置时,就进入异常处理函数保存所有现场,并根据异常向量表跳转到异常入口位置,又跳转到桩子程序。此时桩子程序根据CPU提供的断点信息来判断是哪一个断点引发了跳转到异常处理向量,去CPU的调试寄存器中读取该断点对应的控制块,将该控制块中的补丁代码复制到内存(RAM)中执行。在补丁代码执行完毕后,由CPU继续执行原固件代码。
本申请提供的修复固件代码的方法利用了CPU内部的断点机制,可以根据CPU支持的最大断点数量采用少量额外的非易失性存储器硬件来写入补丁代码,实现对原固件代码的修复或更新。与中国发明专利申请CN106164860A相比,本申请所述方法不需要额外的支持启动的硬件设备和技术,降低了实现成本,提高了可靠性。由于CPU的断点分为读断点、写断点、代码执行断点三种,因此可以灵活地控制在读取某个地址、写入某个地址、执行某个地址的指令时对原固件代码打补丁从而修复系统。
请参阅图3,本申请提供的修复固件代码的系统包括写入单元和修复单元。
所述写入单元用于将包含桩子程序在内的固件代码在硬件设备的制造过程中一次性地写入到硬件设备的非易失性存储器一中。所述非易失性存储器一具有数据一旦写入就无法更改或删除的特性。
所述修复单元用于在硬件设备的非易失性存储器二中写入控制块。修复单元仅在需要对原固件代码进行新增、修改或删除代码时才工作。所述非易失性存储器二可以采用可以反复擦写的存储器。
请参阅图4,本申请提供的修复固件代码的系统还包括硬件设备的CPU、断点设置单元、断点执行单元。
所述硬件设备的CPU用来执行固件代码,一旦执行到桩子程序的位置就由断点设置单元工作,一旦执行到断点位置就由断点执行单元工作。
所述断点设置单元用来根据硬件设备的非易失性存储器二中的每个控制块在硬件设备的CPU的寄存器中分别设置为断点,所设置的断点的数量与控制块的数量相同,并且每个断点与每个控制块相对应。所有的控制块均设置为断点后,所述断点设置单元退出工作,交由硬件设备的CPU继续执行原固件代码。
所述断点执行单元用来根据CPU的寄存器提供的信息寻找断点对应的控制块,并执行所述对应的控制块中的补丁代码,在执行完毕后所述断点执行单元退出工作,交由硬件设备的CPU继续执行原固件代码。
本申请提供的修复固件代码的系统与方法相对应,用来对原固件代码进行新增、修改、删除(跳过)代码。
请参阅图5,本申请还提供了一种控制块的数据结构的示例。每个控制块包括一个控制字段,还包括一个或多个程序和/或数据字段,每个控制块的大小可以不同。在程序和/或数据字段中记载有补丁代码。所述补丁代码中包括指令,还可能包括有这些指令所要操作的数据,还可能包括一旦执行完毕所述补丁代码后跳转到原固件代码中的第二位置的指令。
可选地,所述补丁代码中还包括有第一位置的操作类型是读、写、执行的任意一种,从而据此决定所设置的断点类型是读断点、写断点、代码执行断点的一种。
请参阅图6,所述控制字段又被分为X、Y、Z三个区域。X区域用来记录原固件代码中需要修改的一处代码位置即第一位置。假设原固件代码的大小在64KB以内,那么将X区域设为16比特(bit)的长度就足够描述原固件代码的任何一个偏移地址。Y区域用来记录下一个控制块的地址,由于每个控制块的大小可以不同,因此需要从当前控制块了解下一个控制块的地址。Z区域可以根据需要设计一些标志位。例如Z区域的最低比特为1代表该非易失性存储器二为激活状态,需要固件代码中的桩子程序来读取控制块以设置断点以及执行补丁代码。Z区域的最低比特为0代表该非易失性存储器二为非激活状态,固件代码中的桩子程序可以忽略该非易失性存储器二。
综上所述,本申请提供的修复固件代码的方法及其系统是在固件代码中预先植入桩子程序,并引入非易失性存储器二写入控制块;在桩子程序初始化时先将控制块所记载的第一位置设置为CPU的断点,并在执行到断点位置时跳转执行桩子程序,由所述桩子程序执行该断点对应的控制块中的补丁代码,并在执行完毕后继续执行原固件代码。这样当原固件代码出现缺陷时,就可通过本申请提供的方法跳过缺陷部分,而改为执行替换代码,相当于对原固件代码的缺陷部分进行了修复。或者希望为原固件代码增加新内容例如实现新功能时,也可通过本申请提供的方法在断点位置改为执行新增的补丁代码,因此不需要废弃整个硬件,而低成本地对原固件代码进行了更新。
以上仅为本申请的优选实施例,并不用于限定本申请。对于本领域的技术人员来说,本申请可以有各种更改和变化。凡在本申请的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本申请的保护范围之内。