uboot的relocation原理详细分析

[uboot] (番外篇)uboot relocation介绍 uboot relocation 阅读详情

对以下文章的简单总结:
假设u-boot重定位前有如下代码:

rel_dyn_test函数(函数中调用了test_val全局变量)
                链接地址       存放的值
  1. 80e9d400:   ebffc2ef    bl  80e8dfc4 <printf>  
  2. 80e9d404:   e8bd4010    pop {r4, lr}  
  3. 80e9d408:   eaffffef    b   80e9d3cc <test_func>  
  4. 80e9d40c:   80eb75c0    .word   0x80eb75c0  //存放test_val变量的存储地址

test_val变量

  1. 80eb75c0 <test_val>:  
  2. 80eb75c0:   0000000a    .word   0x0000000a  

执行arch/arm/lib/relocate.s中ldr  r1, =__image_copy_start 到 blo copy_loop 的代码后,以上代码变为:


  1. 80e9d400+offset:   ebffc2ef    bl  80e8dfc4 <printf>  
  2. 80e9d404+offset:   e8bd4010    pop {r4, lr}  
  3. 80e9d408+offset:   eaffffef    b   80e9d3cc <test_func>  
  4. 80e9d40c+offset:   80eb75c0    .word   0x80eb75c0  //存放test_val变量的存储地址 


  1. 80eb75c0+offset <test_val>:  
  2. 80eb75c0+offset:   0000000a    .word   0x0000000a  
此时rel_dyn_test函数中存放的test_val地址和实际的test_val存储地址不相等,这时候rel_dyn_test函数是不能正常访问到test_val变量的。
执行arch/arm/lib/relocate.s中fixloop: 到 blo fixloop的代码后,以上代码变为

  1. 80e9d400+offset:   ebffc2ef    bl  80e8dfc4 <printf>  
  2. 80e9d404+offset:   e8bd4010    pop {r4, lr}  
  3. 80e9d408+offset:   eaffffef    b   80e9d3cc <test_func>  
  4. 80e9d40c+offset:   80eb75c0+offset    .word   0x80eb75c0  //存放test_val变量的存储地址 


  1. 80eb75c0+offset <test_val>:  
  2. 80eb75c0+offset:   0000000a    .word   0x0000000a  
此时 rel_dyn_test函数中存放的test_val地址和实际的test_val存储地址就变成一样了。


http://blog.youkuaiyun.com/skyflying2012/article/details/37660265

所谓的relocation,就是重定位,uboot运行后会将自身代码拷贝到sdram的另一个位置继续运行,这个在uboot启动流程分析中说过。

但基于以前的理解,一个完整可运行的bin文件,link时指定的链接地址,load时的加载地址,运行时的运行地址,这3个地址应该是一致的

relocation后运行地址不同于加载地址 特别是链接地址,ARM的寻址会不会出现问题?


新版uboot跟老版uboot不太一样的地方在于新版uboot不管uboot的load addr(entry pointer)在哪里,启动后会计算出一个靠近sdram顶端的地址,将自身代码拷贝到该地址,继续运行。

个人感觉uboot这样改进用意有二,一是为kernel腾出低端空间,防止kernel解压覆盖uboot,二是对于由静态存储器(spiflash nandflash)启动,这个relocation是必须的。


但是这样会有一个问题,relocation后uboot的运行地址跟其链接地址不一致,compiler会在link时确定了其中变量以及函数的绝对地址,链接地址 加载地址 运行地址应该一致,

这样看来,arm在寻址这些变量 函数时找到的应该是relocation之前的地址,这样relocation就没有意义了!


当然uboot不会这样,我们来分析一下uboot下relocation之后是如何寻址的,开始学习之前我是有3个疑问,如下

(1)如何对函数进行寻址调用

(2)如何对全局变量进行寻址操作(读写)

(3)对于全局指针变量中存储的其他变量或函数地址在relocation之后如何操作

搞清楚这3个问题,对于我来说relocation的原理就算是搞明白了。


为了搞清楚这些,在uboot的某一个文件中加入如下代码

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void test_func(void)  
  2. {  
  3.     printf("test func\n");  
  4. }  
  5.   
  6. static void * test_func_val = test_func;  
  7. static int test_val = 10;   
  8.   
  9. void rel_dyn_test()  
  10. {  
  11.     test_val = 20;   
  12.     printf("test = 0x%x\n", test_func);  
  13.     printf("test_func = 0x%x\n", test_func_val);  
  14.     test_func();  
  15. }  
rel_dyn_test函数中就包含了函数指针 变量赋值 函数调用这3种情况,寻址肯定要汇编级的追踪才可以,编译完成后反汇编,得到u-boot.dump(objdump用-D选项,将所有section都disassemble出来)

找到rel_dyn_test函数,如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 80e9d3cc <test_func>:  
  2. 80e9d3cc:   e59f0000    ldr r0, [pc, #0]    ; 80e9d3d4 <test_func+0x8>  
  3. 80e9d3d0:   eaffc2fb    b   80e8dfc4 <printf>  
  4. 80e9d3d4:   80eb1c39    .word   0x80eb1c39  
  5.   
  6. 80e9d3d8 <rel_dyn_test>:  
  7. 80e9d3d8:   e59f202c    ldr r2, [pc, #44]   ; 80e9d40c <rel_dyn_test+0x34>  
  8. 80e9d3dc:   e3a03014    mov r3, #20 ; 0x14   
  9. 80e9d3e0:   e92d4010    push    {r4, lr}  
  10. 80e9d3e4:   e59f1024    ldr r1, [pc, #36]   ; 80e9d410 <rel_dyn_test+0x38>  
  11. 80e9d3e8:   e5823000    str r3, [r2]  
  12. 80e9d3ec:   e59f0020    ldr r0, [pc, #32]   ; 80e9d414 <rel_dyn_test+0x3c>  
  13. 80e9d3f0:   ebffc2f3    bl  80e8dfc4 <printf>  
  14. 80e9d3f4:   e59f301c    ldr r3, [pc, #28]   ; 80e9d418 <rel_dyn_test+0x40>  
  15. 80e9d3f8:   e59f001c    ldr r0, [pc, #28]   ; 80e9d41c <rel_dyn_test+0x44>  
  16. 80e9d3fc:   e5931000    ldr r1, [r3]  
  17. 80e9d400:   ebffc2ef    bl  80e8dfc4 <printf>  
  18. 80e9d404:   e8bd4010    pop {r4, lr}  
  19. 80e9d408:   eaffffef    b   80e9d3cc <test_func>  
  20. 80e9d40c:   80eb75c0    .word   0x80eb75c0  
  21. 80e9d410:   80e9d3cc    .word   0x80e9d3cc  
  22. 80e9d414:   80eb1c44    .word   0x80eb1c44  
  23. 80e9d418:   80eaa54c    .word   0x80eaa54c  
  24. 80e9d41c:   80eb1c51    .word   0x80eb1c51  
。。。

data段中

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 80eb75c0 <test_val>:  
  2. 80eb75c0:   0000000a    .word   0x0000000a  
。。。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 80eaa54c <test_func_val>:  
  2. 80eaa54c:   80e9d3cc    .word   0x80e9d3cc  

rel_dyn_test反汇编后,最后多了一部分从0x80e9d40c开始的内存空间,对比发现这部分内存空间地址上的值竟然是函数需要的变量test_val test_func_val的地址。

网上资料称这些函数末尾存储变量地址的内存空间为Label,(编译器自动分配)


一条条指令来分析。

ldr  r2,   [pc,  #44] ========> r2 = [pc + 0x2c]=======>r2 = [0x80e9d3e0 + 0x2c]=======>r2 =[0x80e9d40c]

需要注意,由于ARM的流水线机制,当前PC值为当前地址加8个字节

这样r2获取的是0x80e9d40c地址的值0x80eb75c0,这就是test_val的值嘛

mov r3, #20======> r3 = 20

对应C函数这应该是为test_val = 20做准备,先跳过后面2条指令,发现

str  r3,   [r2]

很明显了,将立即数20存入0x80eb75c0中也就是test_val中。


这3条指令说明,ARM对于变量test_val的寻址如下:

(1)将变量test_val的地址存储在函数尾端的Label中(这段内存空间是由编译器自动分配的,而非人为)

(2)基于PC相对寻址获取函数尾端Label上的变量地址

(3)对test_val变量地址进行读写操作


再来看其中的几条指令

ldr   r3, [pc,   #28] =====> r3 = [0x80e9d3fc + 0x1c] =====> r3 = [0x80e9d418] ====> r3 = 0x80eaa54c

ldr   r1, [r3] =====> r1 = [0x80eaa54c] ======> r1 = 0x80e9d3cc

0x80e9d3cc这个地址可以看出是test_func的入口地址,这里是printf打印test_func_val的值
可以看出对于函数指针变量的寻址跟普通变量一样。


接下来来看函数的调用,可以看到对于printf以及test_func,使用的是指令bl以及b进行跳转,这2条指令都是相对寻址(pc + offset)

说明ARM调用函数使用的是相对寻址指令bl或b,与函数的绝对地址无关


对于这3种情况的寻址方法已经知道了,那就需要思考一下relocation之后会有什么变化。

将rel_dyn_test  relocation之后可以想象,函数的调用还是没有问题的,因为使用了bl或b相对跳转指令。

但是对于变量的寻址就有问题了,寻址的前2步没有问题,相对寻址获取尾部Label中的变量地址,但获取的变量地址是在 link时就确定下来的绝对地址啊!

而对于指针变量的寻址呢,问题更多了,

首先跟普通变量寻址一样,尾部内存空间的变量地址是link时的绝对地址,再者,指针变量存储的变量指针或者函数指针也是在link时确定的绝对地址,relocation之后这个值也变了!

那uboot是如何来处理这些情况的呢?更准确的说应该是compiler和uboot如何一起来处理这些情况的呢?

这里利用了PIC位置无关代码,通过为编译器指定编译选项-fpic或-fpie产生,
这样编译产生的目标文件包含了PIC所需要的信息,-fpic,-fpie是gcc的PIC编译选项。ld也有PIC连接选项-pie,要获得一个完整的PIC可运行文件,连接目标文件时必须为ld指定-pie选项,

察看uboot的编译选项发现,在arch/arm/config.mk,如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. # needed for relocation  
  2. LDFLAGS_u-boot += -pie  
uboot只指定了-pie给ld,而没有指定-fPIC或-fPIE给gcc。

指定-pie后编译生成的uboot中就会有一个rel.dyn段,uboot就是靠rel.dyn段实现了完美的relocation!

察看u-boot.dump中的rel.dyn段,如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Disassembly of section .rel.dyn:  
  2.   
  3. 80eb7d54 <__rel_dyn_end-0x5c10>:  
  4. 80eb7d54:       80e80020        rschi   r0, r8, r0, lsr #32  
  5. 80eb7d58:       00000017        andeq   r0, r0, r7, lsl r0  
  6. 80eb7d5c:       80e80024        rschi   r0, r8, r4, lsr #32  
  7. 80eb7d60:       00000017        andeq   r0, r0, r7, lsl r0  
  8. 80eb7d64:       80e80028        rschi   r0, r8, r8, lsr #32  
  9. 80eb7d68:       00000017        andeq   r0, r0, r7, lsl r0  
  10. 。。。  
  11. <span style="color:#FF0000;">80eba944:       80e9d40c        rschi   sp, r9, ip, lsl #8  
  12. 80eba948:       00000017        andeq   r0, r0, r7, lsl r0  
  13. 80eba94c:       80e9d410        rschi   sp, r9, r0, lsl r4  
  14. 80eba950:       00000017        andeq   r0, r0, r7, lsl r0  
  15. 80eba954:       80e9d414        rschi   sp, r9, r4, lsl r4  
  16. 80eba958:       00000017        andeq   r0, r0, r7, lsl r0  
  17. 80eba95c:       80e9d418        rschi   sp, r9, r8, lsl r4  
  18. 80eba960:       00000017        andeq   r0, r0, r7, lsl r0  
  19. 80eba964:       80e9d41c        rschi   sp, r9, ip, lsl r4  
  20. 80eba968:       00000017        andeq   r0, r0, r7, lsl r0</span>  
  21. 。。。。  
有没有注意到,rel_dyn_test末尾存储全局变量地址的Label地址也存储在这里,那有什么用呢, 那就来看一下uboot的核心函数relocate_code是如何实现自身的relocation的,

在arch/arm/lib/relocate.S中

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. ENTRY(relocate_code)  
  2.         ldr     r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */  
  3.         subs    r4, r0, r1              /* r4 <- relocation offset */  
  4.         beq     relocate_done           /* skip relocation */  
  5.         ldr     r2, =__image_copy_end   /* r2 <- SRC &__image_copy_end */  
  6.   
  7. copy_loop:  
  8.         ldmia   r1!, {r10-r11}          /* copy from source address [r1]    */  
  9.         stmia   r0!, {r10-r11}          /* copy to   target address [r0]    */  
  10.         cmp     r1, r2                  /* until source end address [r2]    */  
  11.         blo     copy_loop  
  12.   
  13.         /* 
  14.          * fix .rel.dyn relocations 
  15.          */  
  16.         ldr     r2, =__rel_dyn_start    /* r2 <- SRC &__rel_dyn_start */  
  17.         ldr     r3, =__rel_dyn_end      /* r3 <- SRC &__rel_dyn_end */  
  18. fixloop:  
  19.         ldmia   r2!, {r0-r1}            /* (r0,r1) <- (SRC location,fixup) */  
  20.         and     r1, r1, #0xff  
  21.         cmp     r1, #23                 /* relative fixup? */  
  22.         bne     fixnext  
  23.   
  24.         /* relative fix: increase location by offset */  
  25.         add     r0, r0, r4  
  26.         ldr     r1, [r0]  
  27.         add     r1, r1, r4  
  28.         str     r1, [r0]  
  29. fixnext:  
  30.         cmp     r2, r3  
  31.         blo     fixloop  
  32.   
  33. relocate_done:  
前半部分在uboot启动流程中讲过,将__image_copy_start到__image_copy_end之间的数据进行拷贝

来看一下arm的link script,在arch/arm/cpu/u-boot.lds,如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")  
  2. OUTPUT_ARCH(arm)  
  3. ENTRY(_start)  
  4. SECTIONS  
  5. {  
  6.         . = 0x00000000;  
  7.   
  8.         . = ALIGN(4);  
  9.         .text :  
  10.         {  
  11.                 *(.__image_copy_start)  
  12.                 CPUDIR/start.o (.text*)  
  13.                 *(.text*)  
  14.         }  
  15.   
  16.         . = ALIGN(4);  
  17.         .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }  
  18.   
  19.         . = ALIGN(4);  
  20.         .data : {  
  21.                 *(.data*)  
  22.         }  
  23.   
  24.         . = ALIGN(4);  
  25.   
  26.         . = .;  
  27.   
  28.         . = ALIGN(4);  
  29.         .u_boot_list : {  
  30. <pre name="code" class="cpp">                KEEP(*(SORT(.u_boot_list*)));  
  31.         }  
  32.   
  33.         . = ALIGN(4);  
  34.   
  35.         .image_copy_end :  
  36.         {  
  37.                 *(.__image_copy_end)  
  38.         }  
  39.   
  40.         .rel_dyn_start :  
  41.         {  
  42.                 *(.__rel_dyn_start)  
  43.         }  
  44.   
  45.         .rel.dyn : {  
  46.                 *(.rel*)  
  47.         }  
  48.   
  49.         .rel_dyn_end :  
  50.         {  
  51.                 *(.__rel_dyn_end)  
  52.         }  
  53.   
  54.         .end :  
  55.         {  
  56.                 *(.__end)  
  57.         }  
  58.   
  59.         _image_binary_end = .;   

 
可以看出__image_copy_start---end之间包括了text data rodata段,但是没有包括rel_dyn。 

继续看relocate_code函数,拷贝__image_copy_start----end之间的数据,但没有拷贝rel.dyn段。

首先获取__rel_dyn_start地址到r2,将start地址上连续2个4字节地址的值存在r0 r1中

判断r1中的值低8位,如果为0x17,则将r0中的值加relocation offset。

获取以此r0中值为地址上的值,存到r1中

将r1中值加relocation offset,再存回以r0中值为地址上。

以此循环,直到__rel_dyn_end。

这样读有些拗口。来以咱们的rel_dyn_test举例子。

上面rel.dyn段中有一段如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 80eba944:       80e9d40c        rschi   sp, r9, ip, lsl #8  
  2. 80eba948:       00000017        andeq   r0, r0, r7, lsl r0  
按照上面的分析,判断第二个四字节为0x17,r0中存储为0x80e9d40c。这个是rel_dyn_test末尾Label的地址啊,

将r0加上relocation offset,则到了relocation之后rel_dyn_test的末尾Label。

获取r0为地址上的值到r1中,0x80eb75c0,可以看到,这个值就是变量test_val的首地址啊。

最后将r1加上relocation offset,写回以r0为地址上。意思是将变量test_val地址加offset后写回到relocation之后rel_dyn_test的末尾Label中。

这样relocate_code完成后,再来看对test_val的寻址。寻址第三步获取到的是修改之后的relocation addr啊,这样就可以获取到relocation之后的test_val值!


对于普通变量寻址是这样,那对于指针变量呢,如test_func_val呢?

获取test_func_val relocation后地址的步骤跟上面一样,但是我们在获取test_func_val的值时要注意,这个变量存储的是函数test_func指针,之前是0x80e9d3cc,relocation之后就变化了,所以test_func_val的值也应该变化,这个该怎么办?

方法是一样的,可以在rel.dyn段中找到如下一段:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 80ebc18c:       80eaa54c        rschi   sl, sl, ip, asr #10  
  2. 80ebc190:       00000017        andeq   r0, r0, r7, lsl r0  
这上面存储的是test_func_val的地址,按照relocate_code的操作,完成后80eaa54c + offset上的值也应该+offset了。

这就解决了,test_func_val的值也就是test_func的地址也被修改为relocation之后的地址了。


网上查阅资料,这里对于rel.dyn段中每一个rel section(8个字节)第二个4字节,0x17,是一种label的类型R_ARM_RELATIVE,

经过上面uboot的relocate_code后,我们提出的3个问题的寻址都可以正常工作。


还有一个疑问,是谁来决定哪些label放到rel.dyn中,特别是对于存储指针的变量,如何分辨,这样看来,是compiler的ld来完成的这个工作,将所有需要relocate的label放到rel.dyn段中,真是牛逼的compiler啊!


总结一下,可以看出,

使用-pie选项的compiler,将需要relocate的值(全局变量地址  函数入口地址)的地址存储在rel.dyn段中,uboot运行中relocate_code遍历rel.dyn段,根据rel.dyn中存储的值,对以(这些值+offset)为地址上的值进行了relocate,完成对所有需要relocate的变量的修改!。。。。还是有些拗口。。。

需要注意的是,在uboot的整个relocate_code中rel.dyn不仅没有拷贝,也没有修改,修改只是针对rel.dyn中值+offset为地址上的值!


查阅网上资料,compiler在cc时加入-fPIC或-fPIE选项,会在目标文件中生成GOT(global offset table),将本文件中需要relocate的值存放在GOT中,函数尾部的Label来存储GOT的offset以及其中变量的offset,变量寻址首先根据尾部Label相对寻址找到GOT地址,以及变量地址在GOT中的位置,从而确定变量地址,这样对于目标文件统一修改GOT中的值,就修改了变量地址的offset,完成了relocation。

ld时加入-pie选项,就会将GOT并入到rel.dyn段中,uboot在relocate_code中统一根据rel.dyn段修改需要relocation的数值。

uboot中ld使用-pie而cc没有使用-fPIC或-fPIE,目标文件中就不会生成GOT,函数中寻址还是在尾部Label中直接存储变量的绝对地址,但这个Label同样存在rel.dyn中,uboot根据rel.dyn段修改Label上的值,就完成了relocation。

这样不仅节省了每个目标文件的GOT段,而且不需要去相对寻址GOT,直接修改函数尾部Label所存储的变量地址就可以啦!


uboot的relocation就是如此!


uboot relocation 阅读详情

相关推荐

ESP32实战:破解校园网WPA2-Enterprise认证的完整指南

本文详细介绍了如何使用ESP32开发板破解校园网WPA2-Enterprise认证的完整指南。通过硬件准备、环境搭建、核心代码实现及常见问题排查,帮助开发者解决企业级WiFi连接难题,特别适用于校园网环境下的物联网设备开发。

weixin_29194817的博客 456

uboot-relocation学习总结

近期学习uboot,在relocation部分看了不少大神的分析,下面将自己的理解写下来,也是对此部分功能的学习巩固。   1.1 为什么要relocation   uboot从SDRAM低位拷贝到高位后,各指令存储地址改变,对位置无法指令的执行,不受影响;但位置相关指令的执行,比如说读取一个全局变量(存储在一个绝对地址处),按照之前的寻址无法找到拷贝后的变量值,导致程序执行错误,这时即需

XY_2206的博客 984

进阶数据结构——链式前向星

链式前向星是一种进阶的数据结构,主要用于图的存储。我希望大家先看这个视频(蓝色字体点进去) 不然你很难理解的。在图论中,图的存储方式主要有邻接矩阵和邻接表两种。邻接矩阵虽然建图简单方便,但占内存较大,节点数量稍微大点的题目就难以使用(适合稠密图);而邻接表虽然节省空间,但其指针形式难写易错,且vector形式的读取速度较慢,易导致大数据下的超时(TLE)。针对上述问题,链式前向星作为一种折中的方式应运而生。链式前向星本质上是一种静态链表,它将数据以链表形式连接在一起。

ycs66的博客 2137

u-boot relocate_code原理简单说明

对新版uboot的relocate_code原理做了简单的介绍。

ty的专栏 7462

ERA5数据批量下载

ERA5再分析数据的IDM接管下载

qq_38734327的博客 3035

2026软考中级-软件设计师笔记(送最新视频教程)

核心口诀:运控存输输(运算器、控制器、存储器、输入、输出)例题(2019年上半年):核心公式:数字签名流程:数字证书作用:死锁4个必要条件:死锁判断公式:处理策略:程序设计语言的四大核心成分:顺序表操作(时间复杂度):链表操作(时间复杂度):核心思想:频率高的字符用短编码,频率低的用长编码 → 最小化总编码长度构造步骤(贪心算法):前提:有序表(升序/降序) 步骤:时间复杂度:O(log₂n) 例:查找中核心思想:用哈希函数将关键字映射到存储位置 哈希冲突:不同关键字映射到同一位置 → 用链地址法或开放定址

36万+

u-boot-2021.01(imx6ull)启动流程分析之四:relocate_code和relocate_vectors重定位分析

3.4.3 relocate_code 顾名思义,代码重定位。 /* file: arch/arm/lib/relocate.S */ ENTRY(relocate_code) ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */ subs r4, r0, r1 /* r4 <- relocation offset */ beq relocate_done /* skip relocation */ l

weixin_44498318的博客 1345

[QMT量化交易小白入门]-十二、QMT回测龙头打首板和连板的策略

class a():passA = a() #创建空的类的实例 用来保存委托状态field_list定义了需要的市场数据字段,而类a用于保存交易状态。

木头大左的博客 4760

[UBOOT]uboot的relocation原理详细分析

转自:http://blog.youkuaiyun.com/skyflying2012/article/details/37660265 最近在一直在做uboot的移植工作,uboot中有很多值得学习的东西,之前总结过uboot的启动流程,但uboot一个非常核心的功能没有仔细研究,就是uboot的relocation功能。 这几天研究下uboot的relocation功能,记录在此,跟大家共

be happy 1347

600份国家自然基金申报书--模板

600份国家自然基金申报书--模板

需要远程指导仿真实验、代码有问题的,请后台私信或者关注公众号 4188

vxWorks下dosFs文件系统的创建

文件系统,是指操作系统根据目录和文件的组织形式在磁盘设备上应用的一种设备驱动,不同的文件系统对目录和文件有不同的限制(如目录名限制,文件大小限制等)。VxWorks支持多种文件系统,比较重要的有:1、dosFs:适用于块存取设备(比如硬盘、软盘),和MS-DOS文件系统兼容;2、rawFs:提供了一种简单的原始文件系统。该文件系统将整个硬盘当作一个单独的大文件;3、cdromFs:允许系统从按照I

技术联盟 1万+

Uboot的relocation原理

&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;版权声明:本文为博主kerneler辛苦原创,未经允许不得转载。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https://blog.youkuaiyun.com

qq_40788950的博客 313

ESP32 DW1000 UWB 室内定位系统

详细介绍ESP32 DW1000 UWB 室内定位系统的设计演示demo。

DT程序员的博客 1662

uboot的relocation原理具体分析

近期在一直在做uboot的移植工作,uboot中有非常多值得学习的东西。之前总结过uboot的启动流程,但uboot一个非常核心的功能没有细致研究。就是uboot的relocation功能。 这几天研究下uboot的relocation功能,记录在此,跟大家共享。 自己辛苦编辑,转载请注明出处。谢谢! 所谓的relocation,就是重定位,uboot执行后会将自身代码复制到...

weixin_34392435的博客 248

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

[uboot] uboot relocation介绍

转自https://blog.youkuaiyun.com/ooonebook/article/details/53047992 以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为例   [uboot] uboot流程系列: [project X] tiny210(s5pv210)上电启动流程(BL0-BL2) [uboot] (第一章)uboot流程——概述 [u...

1226

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

上一篇: 经验
下一篇: linux下实现U盘和sd卡的自动挂载
EmSoftEn
博客等级 码龄12年 40粉丝 63原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值