打开 u-boot.lds
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
 . = 0x00000000;
 . = ALIGN(4);
 .text :
 {
 *(.__image_copy_start)
 *(.vectors)
 arch/arm/cpu/armv7/start.o (.text*)
 *(.text*)
 }
。。。。。。。。。
 
 
_start 在文件 arch/arm/lib/vectors.S
.globl _start
    .section ".vectors", "ax"

_start:

#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
.word CONFIG_SYS_DV_NOR_BOOT_CFG
#endif

// 相对跳转和绝对跳转

// https://blog.csdn.net/u013368345/article/details/91882554

b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq

。。。。。

“.section ".vectors", "ax”可以得到,此代码存放在.vectors 段里面
grep -nR "__image_copy_start" u-boot.map得  0x0000000087800000, 因此.text地址为0x87800000
猜测.text地址为 连接时被 -Ttext 0x87800000改写了
 
 

reset函数在文件arch/arm/cpu/armv7/start.S

reset:  
  b save_boot_params
 
ENTRY(save_boot_params)  
  b save_boot_params_ret
 
save_boot_params_ret:  

// 9种模式 [4:0]

// 10000 USER(user)

// 10001 FIQ(fiq)

// 10010 IRQ(irq)

// 10011 Supervisor(svc)

// 10110 Monitor(mon)

// 10111 Abort(abt)

// 11010 Hyp(hyp)

// 11011 Undefined(und)

// 11111 System(sys)

  mrs r0, cpsr                    // r0 = cps
  and r1, r0, #0x1f     @ mask mode bits      // r1 = r0&0x1F
  teq r1, #0x1a       @ test for HYP mode       // test (r1 == 0x1A)  判断当前处理器模式是否处于 Hyp 模式
  bicne r0, r0, #0x1f     @ clear all mode bits   // 如果不处于 Hyp 模式 r0 &= ~0x1F
  orrne r0, r0, #0x13     @ set SVC mode    //  如果不处于 Hyp 模式 r0 |= 0x13   设置SVC模式
  orr r0, r0, #0xc0     @ disable FIQ and IRQ   // r0 |= 0xC0, 最后 r0 应该是0xD3
  msr cpsr,r0                    // cps = r0, 最终CPU 处于 SVC32 模式,并且关闭FIQ 和 IRQ 这两个中断

  

 
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
  /* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
  mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register
    // CR_V 在 arch/arm/include/asm/system.h #define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */
    // 这里主要是 r0 &= ~(1<<13),将 V 清零,目的就是为了接下来的向量表重定位
    // 当V为 0 的时候向量表基地址为 0X00000000,软件可以重定位向量表。为 1 的时候向量表基地址为 0XFFFF0000,软件不能重定位向量表
  bic r0, #CR_V @ V = 0                  
  mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTLR Register
 
  /* Set vector address in CP15 VBAR register */
  ldr r0, =_start
  mcr p15, 0, r0, c12, c0, 0 @Set VBAR  // 将 r0 寄存器的值(向量表值)写入到 CP15 的 c12 寄存器中,也就是 VBAR 寄存器, 中断向量被重定向为_start
#endif
  

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
  bl cpu_init_cp15          // 函数 cpu_init_cp15 用来设置 CP15 相关的内容,比如关闭 MMU 啥的
  bl cpu_init_crit          
 #endif
  bl _main
 
ENTRY(cpu_init_cp15)
  // Invalidate L1 I/D
  mov r0, #0   @ set up for MCR
  mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
  mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
  mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
  mcr p15, 0, r0, c7, c10,4 @ DSB
  mcr p15, 0, r0, c7, c5, 4 @ ISB
 
  // disable MMU stuff and caches
  mrc p15, 0, r0, c1, c0, 0
  bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
  bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
  orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
  orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
#ifdef CONFIG_SYS_ICACHE_OFF
  bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache
#else
  orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
#endif
  mcr p15, 0, r0, c1, c0, 0
  ......
   mov pc, r5 @ back to my caller
ENDPROC(cpu_init_cp15)
 
ENTRY(cpu_init_crit)  
  b lowlevel_init @ go setup pll,mux,memory
ENDPROC(cpu_init_crit)
 
函数 lowlevel_init 在文件 arch/arm/cpu/armv7/lowlevel_init.S

ENTRY(lowlevel_init)
  // Setup a temporary stack. Global data is not available yet.
  // CONFIG_SYS_INIT_SP_ADDR 在 include/configs/mx6ullevk.h 文件中
  // #define CONFIG_SYS_INIT_RAM_ADDR     IRAM_BASE_ADDR
  // #define CONFIG_SYS_INIT_RAM_SIZE     IRAM_SIZE

  // #define CONFIG_SYS_INIT_SP_OFFSET    (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)

  // #define CONFIG_SYS_INIT_SP_ADDR     (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
 
  // IRAM_BASE_ADDR 和 IRAM_SIZE 在文件arch/arm/include/asm/arch-mx6/imx-regs.h
  // #define IRAM_BASE_ADDR 0x00900000  

  // #if !(defined(CONFIG_MX6SX) || defined(CONFIG_MX6UL) ||  defined(CONFIG_MX6SLL) || defined(CONFIG_MX6SL))
  //   #define IRAM_SIZE 0x00040000
  //  #else
  //   #define IRAM_SIZE 0x00020000
  // #endif  
  // 最终得
  // CONFIG_SYS_INIT_RAM_ADDR = IRAM_BASE_ADDR = 0x00900000。
  // CONFIG_SYS_INIT_RAM_SIZE = IRAM_SIZE = 0x00020000 =128KB。
  

  // GENERATED_GBL_DATA_SIZE的值,在文件include/generated/generic-asm-offsets.h  
  // #define GENERATED_GBL_DATA_SIZE 256    // GENERATED_GBL_DATA_SIZE 的含义为(sizeof(struct global_data) + 15) & ~15
  // #define GENERATED_BD_INFO_SIZE 80
  // #define GD_SIZE 248
  // #define GD_BD 0
  // #define GD_MALLOC_BASE 192
  // #define GD_RELOCADDR 48
  // #define GD_RELOC_OFF 68
  // #define GD_START_ADDR_SP 64  
  // 最终得
  // CONFIG_SYS_INIT_SP_OFFSET
  //   = (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
  //   = 0x00020000 – 256 = 0x1FF00。
  // CONFIG_SYS_INIT_SP_ADDR
  //   = (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
  //   = 0x00900000 + 0X1FF00 = 0X0091FF00
 
  // 此时 sp 指向 0X91FF00,这属于 IMX6UL/IMX6ULL 的内部 ram
  ldr sp, =CONFIG_SYS_INIT_SP_ADDR //  0X0091FF00, 因为内部RAM为[0x00900000~0x00920000),  然后末端需要预留一个GD的空间
  bic sp, sp, #7      /* 8-byte alignment for ABI compliance */  // 已经8字节对齐了,这里sp没变化
#ifdef CONFIG_SPL_DM
  mov r9, #0
#else
 
/* Set up global data for boards that still need it. This will be removed soon. */
#ifdef CONFIG_SPL_BUILD
  ldr r9, =gdata
#else 
  #ifdef CONFIG_SPL_BUILD    
    // GD_SIZE 同样在 generic-asm-offsets.h, 大小为248,  0X0091FF00-248=0X0091FE08
    sub sp, sp, #GD_SIZE    
    bic sp, sp, #7    
    mov r9, sp    // 这里r9作为global_data_t结构体指针
  #endif
#endif
  

  push {ip, lr}  
  bl s_init  
  pop {ip, pc}
 
ENDPROC(lowlevel_init)

s_init 函数定义在文件arch/arm/cpu/armv7/mx6/soc.c

void s_init(void)
{
  struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
  struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  u32 mask480;
  u32 mask528;
  u32 reg, periph1, periph2;

  if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL) ||
    is_cpu_type(MXC_CPU_MX6ULL) || is_cpu_type(MXC_CPU_MX6SLL))
    return;    // 对于MXC_CPU_MX6ULL, 这里什么都没做

  /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
  * to make sure PFD is working right, otherwise, PFDs may
  * not output clock after reset, MX6DL and MX6SL have added 396M pfd
  * workaround in ROM code, as bus clock need it
  */

  mask480 = ANATOP_PFD_CLKGATE_MASK(0) |
    ANATOP_PFD_CLKGATE_MASK(1) |
    ANATOP_PFD_CLKGATE_MASK(2) |
    ANATOP_PFD_CLKGATE_MASK(3);
  mask528 = ANATOP_PFD_CLKGATE_MASK(1) |
  ANATOP_PFD_CLKGATE_MASK(3);

  reg = readl(&ccm->cbcmr);
  periph2 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK)
    >> MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET);
  periph1 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
    >> MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET);

  /* Checking if PLL2 PFD0 or PLL2 PFD2 is using for periph clock */
  if ((periph2 != 0x2) && (periph1 != 0x2))
    mask528 |= ANATOP_PFD_CLKGATE_MASK(0);

  if ((periph2 != 0x1) && (periph1 != 0x1) &&
    (periph2 != 0x3) && (periph1 != 0x3))
    mask528 |= ANATOP_PFD_CLKGATE_MASK(2);

  writel(mask480, &anatop->pfd_480_set);
  writel(mask528, &anatop->pfd_528_set);
  writel(mask480, &anatop->pfd_480_clr);
  writel(mask528, &anatop->pfd_528_clr);
}

 
save_boot_params_ret
   ->  cpu_init_crit -> lowlevel_init -> s_init 
  -> _main
 
_main 函数定义在文件 arch/arm/lib/crt0.S

ENTRY(_main)

  // Set up initial C runtime environment and call board_init_f(0).

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
  ldr sp, =(CONFIG_SPL_STACK)
#else
  ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)   // 设置 sp 指针为 CONFIG_SYS_INIT_SP_ADDR,也就是 sp 指向 0X0091FF00

#endif
#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
  mov r3, sp
  bic r3, r3, #7
  mov sp, r3
#else
  bic sp, sp, #7 /* 8-byte alignment for ABI compliance */  // sp 做 8 字节对齐

#endif
  mov r0, sp      // r0=0X0091FF00

  bl board_init_f_alloc_reserve  // board_init.c中, 参数为r0的值

  mov sp, r0      //  top=0X0091FA00,   内存布局为gd_t: [0X0091FA00, 0X0091FB00-8)  alloc:[0X0091FB00, 0X0091FF00)

  /* set up gd here, outside any C code */  

  // include/asm-generic/global_data.h中定义了 typedef struct global_data {...} gd_t;
  // arch/arm/include/asm/global_data.h中有#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9"), 地址0X0091FA00

  mov r9, r0      

  bl board_init_f_init_reserve  // board_init.c中, 参数为r0的值, 最终gd->malloc_base=0X0091FB00这个也就是 early malloc 的起始地址

  mov r0, #0
  bl board_init_f     // 函数定义在文件 common/board_f.c 中!主要用来初始化 DDR,定时器,完成代码拷贝

#if ! defined(CONFIG_SPL_BUILD)  

  // 重新设置环境(sp 和 gd)、获取 gd->start_addr_sp 的值赋给 sp,在函数 board_init_f
  // 中会初始化 gd 的所有成员变量,其中 gd->start_addr_sp=0X9EF44E90, 所以这里相当于设置
  // sp=gd->start_addr_sp=0X9EF44E90。0X9EF44E90 是 DDR 中的地址,说明新的 sp 和 gd 将会存
  // 放到 DDR 中,而不是内部的 RAM 了。GD_START_ADDR_SP=64

  ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
  mov r3, sp
  bic r3, r3, #7
  mov sp, r3
#else
  bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
#endif

  // 获取 gd->bd 的地址赋给 r9,此时 r9 存放的是老的 gd,这里通过获取 gd->bd 的地址来计算出新的 gd 的位置。GD_BD=0

  ldr r9, [r9, #GD_BD] /* r9 = gd->bd */    

  // 新的 gd 在 bd 下面,所以 r9 减去 gd 的大小就是新的 gd 的位置,获取到新的 gd的位置以后赋值给 r9。

  sub r9, r9, #GD_SIZE /* new GD is below bd */

  adr lr, here  // 后面执行其他函数返回here

  ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */

  // lr 中的 here 要使用重定位后的位置

  add lr, lr, r0
#if defined(CONFIG_CPU_V7M)
  orr lr, #1 /* As required by Thumb-only */
#endif
  ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ // uboot要从0x87800000复制到0X9FF47000

  b relocate_code  //  arch/arm/lib/relocate.S

here:
  /*
  * now relocate vectors
  */

  bl relocate_vectors // arch/arm/lib/relocate.S

  /* Set up final (full) environment */

  bl c_runtime_cpu_setup /* we still call old routine here */  // arch/arm/cpu/armv7/start.S

#endif
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
# ifdef CONFIG_SPL_BUILD
  /* Use a DRAM stack for the rest of SPL, if requested */
  bl spl_relocate_stack_gd
  cmp r0, #0
  movne sp, r0
  movne r9, r0
# endif

  // 清除bss开始
  ldr r0, =__bss_start /* this is auto-relocated! */

#ifdef CONFIG_USE_ARCH_MEMSET
  ldr r3, =__bss_end /* this is auto-relocated! */
  mov r1, #0x00000000 /* prepare zero to clear BSS */

  subs r2, r3, r0 /* r2 = memset len */
  bl memset
#else
  ldr r1, =__bss_end /* this is auto-relocated! */
  mov r2, #0x00000000 /* prepare zero to clear BSS */

  clbss_l:cmp r0, r1 /* while not at end of BSS */
#if defined(CONFIG_CPU_V7M)
  itt lo
#endif
  strlo r2, [r0] /* clear 32-bit BSS word */
  addlo r0, r0, #4 /* move to next */
  blo clbss_l

// 清除bss完成
#endif

#if ! defined(CONFIG_SPL_BUILD)
  bl coloured_LED_init
  bl red_led_on
#endif

  // 第一个参数是 gd,因此读取 r9 保存到 r0 里面

  // 设置函数 board_init_r 的第二个参数是目的地址,因此 r1= gd->relocaddr

  /* call board_init_r(gd_t *id, ulong dest_addr) */
  mov r0, r9 /* gd_t */
  ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */
  /* call board_init_r */
#if defined(CONFIG_SYS_THUMB_BUILD)
  ldr lr, =board_init_r /* this is auto-relocated! */
  bx lr
#else
  ldr pc, =board_init_r /* this is auto-relocated! */
#endif
  /* we should not return here. */
#endif

ENDPROC(_main)

 可见_main主要是 调用了board_init_f、relocate_code、relocate_vectors 和 board_init_r 这 4 个函数

board_init.c中的board_init_f_alloc_reserve

ulong board_init_f_alloc_reserve(ulong top)
{
  /* Reserve early malloc arena */
#if defined(CONFIG_SYS_MALLOC_F)  

  // CONFIG_SYS_MALLOC_F_LEN=0X400( 在文件 include/generated/autoconf.h

  top -= CONFIG_SYS_MALLOC_F_LEN;
#endif
  /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */

  //  sizeof(struct global_data)=248(GD_SIZE 值),   最终top = 0X0091FF00 -> top=0X0091FA00

  top = rounddown(top-sizeof(struct global_data), 16);

  return top;
}

board_init.c中的board_init_f_init_reserve

void board_init_f_init_reserve(ulong base)
{
  struct global_data *gd_ptr;
#ifndef _USE_MEMCPY
  int *ptr;
#endif

  /*
  * clear GD entirely and set it up.
  * Use gd_ptr, as gd may not be properly set yet.
  */

  gd_ptr = (struct global_data *)base;
  /* zero the area */
#ifdef _USE_MEMCPY
  memset(gd_ptr, '\0', sizeof(*gd));
#else
  for (ptr = (int *)gd_ptr; ptr < (int *)(gd_ptr + 1); )
    *ptr++ = 0;
#endif
  /* set GD unless architecture did it already */
#if !defined(CONFIG_ARM)
  arch_setup_gd(gd_ptr);
#endif
  /* next alloc will be higher by one GD plus 16-byte alignment */
  base += roundup(sizeof(struct global_data), 16);

  /*
  * record early malloc arena start.
  * Use gd as it is now properly set for all architectures.
  */

#if defined(CONFIG_SYS_MALLOC_F)
  /* go down one 'early malloc arena' */

// arch/arm/include/asm/global_data.h中有

//  #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9")

// 所以gd的指针来自这里

  gd->malloc_base = base;    // 16字节对齐后 gd->malloc_base=0X0091FB00这个也就是 early malloc 的起始地址

  /* next alloc will be higher by one 'early malloc arena' size */
  base += CONFIG_SYS_MALLOC_F_LEN;
#endif
}

arch/arm/cpu/armv7/start.S中的c_runtime_cpu_setup

ENTRY(c_runtime_cpu_setup)
/*
* If I-cache is enabled invalidate it
*/
#ifndef CONFIG_SYS_ICACHE_OFF
  mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
  mcr p15, 0, r0, c7, c10, 4 @ DSB
  mcr p15, 0, r0, c7, c5, 4 @ ISB
#endif

  bx lr

ENDPROC(c_runtime_cpu_setup)

uboot启动过程 1的更多相关文章

  1. U-Boot启动过程完全分析

    U-Boot启动过程完全分析 1.1       U-Boot工作过程 U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下: (1)第一阶段的功能 硬件设备初始化 加载U-Boot第二阶段 ...

  2. uboot启动过程理解

    对于2440而言,启动的方式不多.一般就是外界一个NAND FLASH ,2440内部有个NAND FLASH Controller,会自动把NAND FLASH的前4K拷贝到2440的片内SRAM. ...

  3. U-Boot启动过程完全分析<转>

    转载自:http://www.cnblogs.com/heaad/archive/2010/07/17/1779829.html 1.1       U-Boot工作过程 U-Boot启动内核的过程可 ...

  4. 【ARM-Linux开发】U-Boot启动过程--详细版的完全分析

    ---------------------------------------------------------------------------------------------------- ...

  5. U-Boot启动过程

    开发板上电后,执行U-Boot的第一条指令,然后顺序执行U-Boot启动函数.看一下board/smdk2410/u-boot.lds这个链接脚本,可以知道目标程序的各部分链接顺序.第一个要链接的是c ...

  6. tiny4412学习之u-boot启动过程

    这个文档简要分析了tiny4412自带的u-boot的启动过程,这个u-boot启用了mmu,并且命令的接收和执行方式跟以前的不同. 文档下载地址: http://pan.baidu.com/s/1s ...

  7. U-Boot 启动过程和源码分析(第二阶段)-main_loop分析

    1> main_loop  common/main.c /******************************************************************** ...

  8. Am335x u-boot 启动过程中的系统频率配置

    Am335x的时钟结构分为:ADPLLS和ADPLLLJ 1.ADPLLS用来配置Core_CLK,Dispaly_clk,ARM系统CLK(mpu_clk),DDR PLLs_clk 2.ADPLL ...

  9. (一)U-Boot启动过程--详细版的完全分析

    博客地址:http://blog.csdn.net/hare_lee/article/details/6916325

  10. (转载)U-boot启动完全分析

    1.1 U-Boot工作过程 U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下: (1)第一阶段的功能 Ø 硬件设备初始化 Ø 加载U-Boot第二阶段代码到RAM空间 Ø 设置好栈 Ø ...

随机推荐

  1. 群晖NAS搭建外网可访问的calibre

    一.在群晖docker上安装calibre-web 1. 下载相关的镜像文件 打开Docker后点击左侧注册表,在上方搜索栏搜索calibre 然后我们选择使用 technosoft2000/cali ...

  2. 解决linux mint内置无线网卡失效问题

    前言 同学安装了linux mint,但是内置的无线网卡失效,只能通过有线网卡连接,经过查询得到不是缺少驱动的问题,是内核不支持 解决办法 sudo apt install linux-generic ...

  3. chrom jsonview的使用

    在开发中,我们可能要为不同的系统提供接口,并以说明文档的形式提供接口说明,但我们提供的返回json往往会在页面上乱成一团. 这里我们推荐chrome浏览器的小插件jsonview,他不但有利于我们对接 ...

  4. 移除元素-LeetCode27 双指针

    力扣链接:https://leetcode.cn/problems/remove-element/ 题目 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返 ...

  5. 03.Javascript学习笔记2

    1.逻辑运算符 在javascript中与或非对应的逻辑运算符是: && || ! const a = true; const b = false; console.log(a &am ...

  6. JAVA中的注解可以继承吗?

    前言 注解想必大家都用过,也叫元数据,是一种代码级别的注释,可以对类或者方法等元素做标记说明,比如Spring框架中的@Service,@Component等.那么今天我想问大家的是类被继承了,注解能 ...

  7. Mac系统下word论文参考文献更新域

    写论文的时候可能会遇到后续要增加文献的情况 在参考文献增加后会发现文章中的交叉引用的序号并没有更新 下面分享两种情况的处理方法 一.更新全部域 首先确认自己的打印️项是选中的 2.  打开word偏好 ...

  8. SQLMap入门——获取数据库的所有用户

    列出数据库中的所有用户 在当前用户有权读取包含所有用户的表的权限时,使用该命令列出所有管理用户 python sqlmap.py -u http://localhost/sqli-labs-maste ...

  9. SQLMap入门——判断是否存在注入

    假设目标注入点是http://127.0.0.1/sqli-labs-master/Less-1/?id=1,判断其是否存在注入的命令如下: python sqlmap.py -u http://12 ...

  10. 沁恒微(WCH)CH395/392配置使用,代码指南 网路接口芯片 CH395 CH392

    CH395/CH392相关资料可以从官网下载具体连接可以看博客:WCH以太网相关芯片资料总结 里面是WCH官网相关信息的链接. 也可以去Gitee上下载:Gitee链接. STM32控制CH395的例 ...