Embedded System and Security学习笔记

发布于 2022-09-29  869 次阅读


Chapter 2 Microcontroller Basis

2.1 Components of a microcontroller

1. CPU

目前的趋势是多核,分为对称式和不对称式。对称式指的是多个通用core,不对称式指的是一个通用core和多个专用processor。

2. Cache

3. Interrupt Unit

中断用于对异步事件的快速反应,可以是一个简单的寄存器,出发一个interrupt handler;也可以是一个复杂的硬件,对并行的中断进行优先级排序,并在处理器的指令路径中注入一个跳转,使其执行interrupt handler。

4. Debug

调试是与外部调试器的接口(通常是串行接口,JTAG、Uart、USB),用于启动和停止程序以及读写内存。有时trace功能可用于观察处理器内部状态。

5. High Bandwidth Bus

用于连接片上存储器、快速IO、DMA和缓存的总线(32或64位宽)。

6. Slow Bus

用于连接配置寄存器和慢速外设,如定时器和串行IO的慢速总线(16或32位)。

具有低延迟,以防止外设触发某些事件。

7. Bus Bridge

连接不同的总线,用于减少负载,提高总线速度,分离低带宽和高带宽的总线。

8. Memory

RAM,片上易失性存储器,断电后擦除。ROM,非易失性存储器,用于mask programed和存储boot code。Flash、EERPROM、FRAM,非易失,可擦除。

9. MMU/MPU

对内存区域的访问权限进行管理。MMU,虚拟内存和物理地址之间的映射。

10. DMA

从外设直接到内存的数据传输,减少CPU负载,但可能导致总线访问冲突。

11. Fast IO

Ethernet、高速USB、外部存储器接口...通常有很大的收发缓冲区,由DMA提供服务。

12. Slow IO

Uart、全速USB...有很小的缓冲区,可通过字节访问。

13. Accelerators

是用于专门任务的特殊硬件,如AES加密。

14. A/D D/A

与物理世界的接口。

15. Timer

用于时间计算和测量以及脉冲宽度调制。

16. Control

各类控制单元,如启动、电源控制、clock控制和配置管理。

17. Man Machine Interface

与显示器、键盘的接口。

18. HSM(Hardware Security Module)

是作为硬件信任锚的特殊硬件,有独立的CPU和加密加速器。可存储密匙,保护启动顺序和控制访问。

2.2 Characteristics of a CPU Architecture(ARM Cortex-M)

1. Memory

Program memory和Data memory分开。

2. Registers

  • 16个32位寄存器,R0-R7是八个low通用寄存器,R8-R12是五个high通用寄存器,R13是MSP(main stack pointer)或PSP(process stack pointer),R14是link register(用于存储函数返回地址)R15是Program Counter
  • Caller-saved registers: R0-R3, R12

R0: 1st argument, return value. e.g. uint32_t foo(uint32_t 0xFF00FF)

R1: 2nd argument, return value

R2: 3rd argument. e.g. uint8_t bar(uint8_t 12, uint32_t 0xFF00FF, uint16_t 0x1234)

R3: 4th argument. e.g. uint64_t foobar(void * 0x08000000, size_t 0xFFFFFFFF, uint16_t 0x1234, uint16_t 0x5678)

(Further arguments are passed to the stack.)

  • Callee-saved registers: R4-R11
  • SP(Stack Pointer)

SP决定了堆栈上已分配和未分配的内存之间的边界。如果一个函数需要堆栈空间,它就通过减少SP来占用一部分堆栈空间。所有被函数分配的堆栈空间必须在返回前释放(因为否则就会出现内存泄漏,每次调用函数都会浪费堆栈空间),所以函数必须以之前减少的相同数量增加SP,或者简单地将其重置为函数开始前的原始值。这适用于所有被调用者。被调用者要确保一旦完成函数,SP与它的原始值一致,这正是callee-saved registers所需要的行为。

  • LR(Link Register)

LR可以被看作是一种隐藏的参数寄存器,它告诉被调用者返回地址。被调用者不需要保留它的值,除非它希望把ret addr存入PC中。因此,LR与R0-R3非常相似,后者也不需要保留,但其初始值(当被调用者开始执行时)对被调用者的结果很重要。如果调用者在这些寄存器中拥有重要的信息,比如它自己从父级调用中的返回地址,则在进行子程序调用之前,它必须把它们保存在其他地方,因此它符合caller-saved registers的规格。

  • PC(Program counter)

PC与caller-saved register的情况一样,调用者保存了子程序调用后应在PC中结束的值,因为只有调用者知道调用后应执行哪个指令。但它保存在LR中而不是在堆栈中,所以被调用者可以找到它。反过来,被调用者必须恢复PC,就像它是一个被调用者保存的寄存器一样,但不需要保存所需的信息,因为调用者已经这样做了。

  • RSR(Program Status Register):

ApplicationPSR: Negative flag, Zero flag, Carry flag, Overflow flag, Greater-than or Equal flags.

ExecutionPSR: IF-THEN instruction status bits, Thumb state.

InterruptPSR: Exception number of the currently handled exception.

3. Instructions

数据处理指令:

  • ADD, SUB, MUL, DIV, NEG
  • LSL, ASR, LSR. NOT, AND, OR, EOR, … BIC
  • CMP, CMN, TST
  • REV, REV16, SXTB, SXTH, UXTB, UXTH

数据移动(内存)操作:

  • LDR, LDR(S)H, LDR(S)B(从memory取值到register)
  • STR, STRH, STRB (将register值存入memory)
  • PUSH, POP(堆栈操作)
  • MRS(move from special register), MSR(move to special register)

控制程序流、分支:

  • B(跳转到一个label,给PC写入新值)
  • BC(使用处理器中的4个flags决定要不要执行分支)
  • CBZ, CBNZ(检查某寄存器中Z-flag是不是0) ...(跳转)
  • BL, BLX, ...(调用函数,PC值先被复制到LR中)

其他指令:NOP, SLEEP, WAKEUP, BREAK, DEBUG

4. Format of an instruction

opcodeoperand1operand2operand3

opcode: 哪条指令

operand1: 对哪个寄存器操作

operand2: 立即数/ 寄存器/ an immediate shifted register/ a register shifted register

operand3: 寄存器值(optional)

5. Addressing modes

Addressing ModeOperand FieldRegister-file contentsMemory Contents
ImmediateData\\
Register-directRegister addr ->Data\
Register-indirectRegister addr ->Memory addr->Data
Direct(NOT in ARM)Memory addr ->\Data
Indirect(NOT in ARM)Memory addr ->\Memory addr -> Data

6. Role of Stack

堆栈是一个用于保存寄存器内容的内存区域,堆栈的位置是由堆栈指针寄存器(stack pointer register)决定的。通常情况下,堆栈指针从高内存地址开始,在使用堆栈的过程中被递减。

堆栈通常在函数/程序调用过程中使用,存储一个函数的所有局部变量。如果一个子程序被调用,那么CPU的当前状态也必须被存储在堆栈中,包括将在函数中使用的寄存器当前值、PC当前值和函数参数。堆栈空间有限,堆栈中没有大的数组,也没有动态内存。

PUSH Rx:SP减小4字节 -> Rx被存入当前SP指向的区域。

POP Rx:当前SP指向的数据被取到Rx中 -> SP增加4字节。

7. The role of heap

堆是一个内存区域,可用于存储静态数据、动态分配的内存(malloc, calloc)和全局变量。通常情况下,堆是向上增长的。堆的内存不是自动维护的,动态分配的空间必须被释放,而且对内存的访问必须被同步。堆空间通常比栈空间大

2.3 Program generation flow

1. An executable program on PC

High Program Language Code

⬇️

Compiler

⬇️

Assembler ⬅️ Assembly Code

⬇️

Object Files

⬇️

Linker ⬅️ Run time Libs

⬇️

Executable Image File

⬇️

Loader

⬇️

System Memory (RAM) ⬅️ Boot Process ⬅️ OS

2. An executable program in microcontroller

High Program Language Code

⬇️

Compiler

⬇️

Assembler ⬅️ Assembly Code

⬇️

Object Files

⬇️

Real-Time Kernel and Linker Command File ➡️ Linker ⬅️ Reentrant Libs

⬇️

Executable Image File

⬇️

Linker Command File ➡️ Locator

⬇️

ROM Image File

⬇️

ROM Burner or Loader

⬇️

Read only memory

⬇️ initialization

Read write memory

Object code (*.o) File Format: ELF(Executable and Linkable Format)

  • ELF格式有两种用途:Linker将其作为输入,可以与其他对象链接。Loader将其解释为可执行程序
  • 一个ELF文件包含ELF头文件、可选的program header table、sections(或segments)和可选的section header table。
  • 重要的ELF sections:

.text - program code

.data .sdata - initialized data

.bss .sbss - uninitialized data

. rodata - non-volatile default initialization parameters and data

_loader - load code

_wflash - flash programmer code

_monitor - code of a software monitor(debugger)

3. PC和ES对比

PC

  • 程序通过操作系统(OS)加载到PC的RAM中。
  • 库大多是动态链接的
  • 操作系统使用MMU将程序中使用的虚拟地址转换为RAM的物理地址

嵌入式系统

  • 程序在片上ROM/Flash存储器中,并从那里直接执行
  • 程序是静态链接的,有时包括实时操作系统和不同的任务

Chapter 3 Debugging

3.1 Intro

1. Reduce debug effort

Hierarchical debug approach

Higher Level Software - >Applications
Lower Level Software - >OS, Low Level Drivers, Complex Drivers
Hardware - >Processor cores, Buses, Peripherals

2. Debugging Methods

  • 代码仪表:断言、打印语句(通常通过UART或USB连接输出)、实时检查(通过LED灯)
  • 仿真 Simulation
  • 仿真 Emulation
  • 软件调试器
  • 硬件调试器(专门用于调试支持的HW模块)

3. Debugger Features

  • 物理接口
  • Halt after Reset
  • Single Stepping(machine code instructions或high level language statements)
  • Breakpoints(程序计数器+值触发,hardware comparators for Instruction Pointer)
  • Watchpoints(数据地址+值触发,hardware comparators for data address)
  • Trace 跟踪(Program Trace或Data Trace)
  • Profiling 分析

Chapter 4 Interrupts & Exceptions

4.1 Intro

1. The first exception: system start or reset sequence

  • 重要寄存器的初始化:堆栈指针值(在ARM中从地址0x0开始)、程序计数器值(在ARM中从地址0x4开始)、异常(中断和陷阱)被禁用。
  • CPU执行一个分支到存储在程序计数器中的地址,从内存中获取第一条指令。
  • 这第一条程序代码的内容:可直接执行的应用程序、boot loader(将其他代码从外部存储器加载到内部RAM中)、boot loader(通过接收外设Uart、Jtag、以太网和USB的代码在系统中安装SW)。

2. Exception VS Interrupt

Both cause a change in the execution flow by calling a subroutine.

1. Interrupt: caused by an external event

  • devices: disk, network, keyboard
  • clock for timesharing

2. Exception: caused by an internal condition within the processor

  • segmentation fault (access outside program boundaries, illegal access ...). 分段故障(超出程序边界的访问,非法访问)
  • divide by 0
  • overflow
  • page fault (virtual memory ...)

4.2 Interrupt

1. Components of interrupt system

step 1: interrupt event informs the interrupt controller through peripheral. 中断事件通过外围设备通知中断控制器.

step 2: interrupt controller informs CPU with interrupt index. 中断控制器附上中断索引通知CPU.

step 3: CPU saves context into stack. CPU将context保存到堆栈中.

step 4: CPU asks vector table for address of service routine through vector address. CPU通过地址向vector table请求中断程序的地址.

step 5: vector table returns the jump address of service routine to CPU. vector table将中断程序的跳转地址返回给CPU.

step 6: CPU executes the subroutine and acknowledges the peripheral. CPU执行子程序并通知外设.

2. Actions in case of an interrupt (Cortex-M3)

1. 8 registers are pushed to the stack: PC, PSR, R0-R3, R12, LR (caller-saved registers)

2. Program flow is changed, memory location indexed by the interrupt number is loaded to PC

(1 and 2 are parallel)

3. A switch to privileged mode is performed

4. The interrupt number in the IPSR (interrupt priority service register) is updated to allow only higher-priority interrupts.

5. In the LR the processor stores whether it has to return to another interrupt or to a standard program and which mode.

3. Reasons of interrupt latency

1. Time to push current context into stack

2. Time to fetch new instructions for interrupt service routine (memory access latency, speed of memory storing the vector table, fetch code stored at location stored in the vector table)

3. Longest run time of any multi-cycle non-interruptable instruction

4. Resource conflicts (busses used for pending transactions)

5. Interrupt handling times for higher-priority interrupts

4. Measures to reduce the interrupt latency

  • Tail Chaining

如果第2个相同或更低优先级的中断在第1个中断的执行阶段到达,则第2个中断将在第1个中断之后立即执行,而不需unstacking。

  • Late Arrival

如果第2个更高优先级的中断在第1个中断的stacking阶段到达,则第2个中断将首先被执行,然后是第1个中断(tail chain)。

  • Pop Preemption

如果在第1个中断的执行后unstacking时,第2个中断到达了,则unstacking将被停止,第2个将被立即执行

5. Types of interrupts and systems

  • Level triggered

外设向中断控制器发出中断信号,之后软件需要清除外设中的中断位。

  • Edge triggered

如果发生了中断,外设会产生一个规定长度的脉冲。中断事件被存储在中断控制器中,中断被执行后,中断控制器将清除标记。

6. Applications of Interrupts

  • 从睡眠/断电模式中唤醒
  • 定时器中断
  • 处理通信外设
  • 处理具有长运行时间的协处理器
  • 直接内存访问(DMA)

7. How to write Interrupt Service Routines(ISR)?

-- Hardware abstraction layers!

Example CMSIS(Cortex Microcontroller Software Interface Standard)包含:

  • Hardware abstraction layers(HAL)
    SysTick、NVIC、系统控制块、MPU、FPU和core access functions的标准化定义。
  • System exception names
  • 组织头文件的方法
    例如,设备特定中断的命名惯例。
  • 系统初始化的方法
    例如,标准化的SystemInit()函数对于配置设备的时钟系统至关重要。
  • 标准C函数所不支持的用于生成CPU指令的内在函数。
  • 一个确定系统时钟频率的变量,简化了SysTick的设置。

8. Interrupts VS Polling

  • Polling: 一个程序在无休止的循环中检查外设中的某一事件的标志值。
  • Pros: 轮询循环的时间是确定的,整个系统的行为更具有决定性,对事件的反应比中断要快。
  • Cons: 浪费能源(如果使用中断,CPU可以处于睡眠状态),不能平行执行其他任务。

4.3 Exception

1. Exception Types

  • Synchronous/Precise:

Fault: ret addr指向引起异常的指令,exception handler解决这个问题,然后重新启动程序,看起来像什么都没有发生。通常Fault很容易修理,如memory protection(access forbidden)

Trap: ret addr指向刚刚完成的指令之后的那条指令。通常Trap很难修理,不能继续程序,如除以0。

  • Asynchronous/Imprecise:

Abort: ret addr并不总是可靠地提供,因为导致abort的程序不是为了能继续运行下去。

2. Reasons of exception

exception是一种预定义的interrupt,其原因有:

  • 外部事件(non maskable interrupt)
  • 指令(software reset、supervisor call、hypervisor call)。
  • 程序执行过程中发生的故障情况(总线故障、使用故障、内存故障、硬故障)
  • Debug events
  • System timer interrupts

exception可以用来:

  • Debugging of programming errors
  • Scheduling in OS
  • 处理器模式之间的切换
  • 重新配置MPU/MMU

Chapter 5 Boundary Errors and Control Hijacking Attacks

5.1 Stack-based buffer overflow attack

1. Stack Review

  • Last-In First-Out data structure
  • Items can be inserted into the stack with a PUSH
  • Items can be retrieved from the stack with a POP

2. Stack Frame

stack frame是堆栈的一个逻辑分区,每当一个函数被调用时,就会创建一个新的stack frame。

stack frame被用来:

  • 允许函数之间传递变量
  • 存储来自先前函数的变量(callee-saved register)
  • 允许每个子程序使用堆栈而不干扰其他函数
  • 允许子程序使用从堆栈框架到堆栈末端的内存


|return address | (high memory address)

|callee-saved register|??????

|local variables | <- Stack pointer

  • Entry and exit sequences (aka. prologue and epilogue) take care of managing the stack frames. The actual sequences depend on the compiler’s calling conventions.

3. Buffer Overflow

void foo (char *str) 
{
char buff[8];
strcpy(buff, str); 
}
  • 函数strcpy(dst, src)不会检查缓冲区的边界,它每次把字节从src地址复制到dst地址后会递增堆栈指针。
int main(void) 
{
foo(“it will overflow");
return 0; 
}