一、内核裁剪

  内核的裁剪首先就是修改我们的配置文件,即 include/configs/jz2440.h 文件,里面定义的很多宏,我们也许用不上的就要去掉。

 /*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
* Gary Jennejohn <garyj@denx.de>
* David Mueller <d.mueller@elsoft.ch>
*
* Configuation settings for the JZ2440 board.
*
* SPDX-License-Identifier: GPL-2.0+
*/ #ifndef __CONFIG_H
#define __CONFIG_H /*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_S3C24X0 /* This is a SAMSUNG S3C24x0-type SoC */
#define CONFIG_JZ2440 /* on a JZ2440 Board */
#define CONFIG_S3C2440 /* 内存为64M(34000000),34000000 - 33F00000 = 100000 即为1M*/
#define CONFIG_SYS_TEXT_BASE 0x33f00000 #define DEBUG #define CONFIG_SYS_ARM_CACHE_WRITETHROUGH /* input clock of PLL (the JZ2440 has 12MHz input clock) */
#define CONFIG_SYS_CLK_FREQ 12000000 #define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */
#define CONFIG_SETUP_MEMORY_TAGS
#define CONFIG_INITRD_TAG /*
* Hardware drivers
*/
#if 0
#define CONFIG_CS8900 /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE 0x19000300
#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
#else
#define CONFIG_DRIVER_DM9000
#endif /*
* select serial console configuration
*/
#define CONFIG_S3C24X0_SERIAL
#define CONFIG_SERIAL1 1 /* we use SERIAL 1 on JZ2440 */ /************************************************************
* USB support (currently only works with D-cache off)
************************************************************/
#define CONFIG_USB_OHCI
#define CONFIG_USB_OHCI_S3C24XX
#define CONFIG_USB_KEYBOARD
#define CONFIG_USB_STORAGE
#define CONFIG_DOS_PARTITION /************************************************************
* RTC
************************************************************/
#define CONFIG_RTC_S3C24X0 #define CONFIG_BAUDRATE 115200 /*
* BOOTP options
*/
#define CONFIG_BOOTP_BOOTFILESIZE
#define CONFIG_BOOTP_BOOTPATH
#define CONFIG_BOOTP_GATEWAY
#define CONFIG_BOOTP_HOSTNAME /*
* Command line configuration.
*/
#define CONFIG_CMD_BSP
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_NAND
#define CONFIG_CMD_PING
#define CONFIG_CMD_REGINFO
#define CONFIG_CMD_USB #define CONFIG_SYS_HUSH_PARSER
#define CONFIG_CMDLINE_EDITING /* autoboot */
#define CONFIG_BOOTDELAY 5
#define CONFIG_BOOT_RETRY_TIME -1
#define CONFIG_RESET_TO_RETRY
#define CONFIG_ZERO_BOOTDELAY_CHECK #define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 10.0.0.110
#define CONFIG_SERVERIP 10.0.0.1 #if defined(CONFIG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
#endif /*
* Miscellaneous configurable options
*/
#define CONFIG_SYS_LONGHELP /* undef to save memory */
#define CONFIG_SYS_CBSIZE 256
/* Print Buffer Size */
#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
sizeof(CONFIG_SYS_PROMPT)+)
#define CONFIG_SYS_MAXARGS 16
#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE #define CONFIG_DISPLAY_CPUINFO /* Display cpu info */ #define CONFIG_SYS_MEMTEST_START 0x30000000 /* memtest works on */
#define CONFIG_SYS_MEMTEST_END 0x33F00000 /* 63 MB in DRAM */ #define CONFIG_SYS_LOAD_ADDR 0x30800000 /* support additional compression methods */
#define CONFIG_BZIP2
#define CONFIG_LZO
#define CONFIG_LZMA /*-----------------------------------------------------------------------
* Physical Memory Map
*/
#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
#define PHYS_SDRAM_1 0x30000000 /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */ #define PHYS_FLASH_1 0x00000000 /* Flash Bank #0 */ #define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 /*-----------------------------------------------------------------------
* FLASH and environment organization
*/ #define CONFIG_SYS_FLASH_CFI
#define CONFIG_FLASH_CFI_DRIVER
#define CONFIG_FLASH_CFI_LEGACY
#define CONFIG_SYS_FLASH_LEGACY_1Mx16
#define CONFIG_FLASH_SHOW_PROGRESS 45 #define CONFIG_SYS_MAX_FLASH_BANKS 1
#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
#define CONFIG_SYS_MAX_FLASH_SECT (128) #define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE 0x10000
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE /*
* Size of malloc() pool
* BZIP2 / LZO / LZMA need a lot of RAM
*/
#define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024) #define CONFIG_SYS_MONITOR_LEN (448 * 1024)
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE /*
* NAND configuration
*/
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#endif /*
* File system
*/
#define CONFIG_CMD_FAT
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_UBI
#define CONFIG_CMD_UBIFS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
#define CONFIG_YAFFS2
#define CONFIG_RBTREE /* additions for new relocation code, must be added to all boards */
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - \
GENERATED_GBL_DATA_SIZE) #define CONFIG_BOARD_EARLY_INIT_F #endif /* __CONFIG_H */

  编译执行:

  

  do_date 对应着宏 DO_CMD_DATE,去掉此宏

  

  再次编译执行,编译完成。

  

  烧写进开发板。启动。

二、环境变量

2.1 修改分区为nand

  环境变量的设置都会存在flash中,若是未设置分区,就执行save等保存命令,可能会破坏u-boot的启动程序。

  环境变量的设置 对应着宏

  

  不过这段我们不需要,我们需要设置自己的环境变量。

  查找save命令的设置对应的文件,saveenv

  

  

  

  我们只有nand和flash所以只对应这两行。查看common 下的 Makefile:

  

  

  配置成保存环境变量的地方为 nand ,则需要定义宏 CONFIG_ENV_IS_IN_NAND

  进入源文件继续查看,还需要定义宏 CMD_SAVEENV,CMD_SAVEENV宏的定义则依赖下面的程序:

  

  CONFIG_CMD_NAND 我们已经在jz2440.h中定义,所以不需要了。

  saveenv函数中同时涉及到另外两个宏:CONFIG_ENV_RANGE和CONFIG_ENV_OFFSET,一个是ENV的擦除大小,一个是偏移地址。

  

  其中CONFIG_ENV_RANGE 的设置如上,我们可以直接参照 flash的设置,配置这几个宏。

  

  编译,烧写:

  

  结果不对,打开DEBUG开关进行DEBUG

  代码流程中执行到initr_nand,之后就开始执行initr_env,在此函数和其子函数中加入调试代码 查看是否进入其中执行:

  

  

  在函数的头尾加上debug函数,可以在进入的函数中都加上,然后去查函数在哪里调用出错了。编译,烧录:

  

  上面是结尾的打印信息。根据上面的信息理一下代码

 board_init_r
initr_env
debug("start of initr_env \n");
should_load_env()
debug("start of should_load_env() \n");
debug("end of should_load_env() \n");
env_relocate
debug("start of env_relocate(void) \n");
debug("in of env_relocate_spec() \n");
env_relocate_spec();
env_relocate_spec(void) //此函数是未定义CONFIG_ENV_OFFSET_REDUND宏的函数
debug("start of env_relocate(void) \n");
debug("env_relocate_spec in set_default_env\n");
set_default_env("!readenv() failed");
debug("end of env_relocate(void) \n");
debug("end of env_relocate(void) \n");
debug("end of initr_env \n");

  标记红色部分是已经执行了的,可以看出在进入env_relocate_spec时候找不到函数了,此函数并没有进入,但是又确实执行到那一步了,看一下u-boot.dis,看是否执行过此函数

  

  查看一下 env_relocate是否调用此地址函数:

  

  这里又调用 但是执行的时候又出错了,进入了此函数,确没有返回。就是程序运行的时候根本没有进入此函数中。

  查看一下栈的设置以及autoconf.h文件,发现在其中,打开了CONFIG_SYS_MALLOC_F宏,这个宏在原先的设置中我们并没有加入,应该是系统自动给他设定的。

  查看jz2440_defconfig文件,发现里面确实打开了这个宏,注释掉,这个宏在栈的设置中会用到,在crt0.S的代码中有一段跳转到board_init_f_mem 函数,里面有一段代码如下:

 #if defined(CONFIG_SYS_MALLOC_F)
top -= CONFIG_SYS_MALLOC_F_LEN;
gd->malloc_base = top;
#endif

  这里是分配给一小段内存池,使栈下移动。栈往下多移动了 1024KB

  

  同时在我们的默认的config文件中,发现关闭了 CONFIG_CMD_NAND 宏,这个宏必须要打开。

  在配置中,SPL也被打开了,必须关闭

  

  最后重新修改下crt0.S中的代码,如下:

 ENTRY(_main)

 /*
* Set up initial C runtime environment and call board_init_f(0).
* 初始化C运行环境并且调用 board_init_f(0) 函数
*/ /*
* 初始化栈地址
*/
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
ldr sp, =(CONFIG_SPL_STACK)
#else
/* Generic-asm-offsets.h (include\generated)
* #define GENERATED_GBL_DATA_SIZE 192
* JZ2440.h(include\config)
* #define PHYS_SDRAM_1 0x30000000
* #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
* #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
*
* CONFIG_SYS_INIT_SP_ADDR = 0x30000000 + 0x1000 - 192(0xc0) = 0x30000f40
*/
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /* 设置CFIG_SYS_INIT_SP_ADDR定义的地址,include/configs/jz2440.h中定义 */
#endif /* end defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)*/ #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
mov r3, sp
bic r3, r3, #
mov sp, r3
#else
/* sp 的8字节对齐 */
bic sp, sp, # /* 8-byte alignment for ABI compliance */
#endif /* end defined(CONFIG_CPU_V7M) */ /* 设置nand 启动 */
bl nand_init_ll /* 跳转到borad/samsung/jz2440/init.c 中执行 nand_init_ll 函数 */
mov r0, #
ldr r1, =(CONFIG_SYS_TEXT_BASE) /*CONFIG_SYS_TEXT_BASE=0x33f00000 程序的链接地址*/
ldr r2, =0x80000 /* 程序大小 */
bl copy_code_to_sdram /* 拷贝代码到SDRAM */
bl clear_bss /* 清除bss */ ldr pc, =call_board_init_f /* 执行第一阶段初始化 */ call_board_init_f:
mov r0, sp /* r0 = sp */
bl board_init_f_mem /*跳转到 board_init_f_mem 执行*/
mov sp, r0 /* sp = 0x30000000*/ mov r0, #
bl board_init_f /* 调用单板的初始化函数,跳转到 borad_init_f 处执行 */ #if ! defined(CONFIG_SPL_BUILD) /*
* Set up intermediate environment (new sp and gd) and call
* relocate_code(addr_moni). Trick here is that we'll return
* 'here' but relocated.
*/
/*
* 这一段代码是将board_init_f中设置好的start_addr_sp地址值赋给栈指针,使其指向重定位后的栈顶
* 8字节对齐后,将r9设为新的GD地址( gd地址=bd地址-sizeof(gd_t))
*/
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, #
mov sp, r3
#else
bic sp, sp, # /* 8-byte alignment for ABI compliance */
#endif /* defined(CONFIG_CPU_V7M) */ ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */ adr lr, here /*设置返回地址为下面的here,重定位到sdram后返回here运行*/
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off 取重定位地址偏移值 */
add lr, lr, r0 /*返回地址加偏移地址等于重定位后在sdram中的here地址*/ #if defined(CONFIG_CPU_V7M)
orr lr, # /* As required by Thumb-only */
#endif
#if 0
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr 传入参数为重定位地址 */
b relocate_code /*跳到arch/arm/lib/relocate.S中执行*/
#endif here: /*返回后跳到sdram中运行 */
/*
* now relocate vectors
*/
bl relocate_vectors /* Set up final (full) environment */
bl c_runtime_cpu_setup /* we still call old routine here */
#endif /* ! defined(CONFIG_SPL_BUILD) */ #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, #
movne sp, r0
#endif /* end CONFIG_SPL_BULD */
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, # /* move to next */
blo clbss_l
#endif #if ! defined(CONFIG_SPL_BUILD)
bl coloured_LED_init
bl red_led_on
#endif /* call board_init_r(gd_t *id, ulong dest_addr) */
mov r0, r9 /* gd_t */
ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */
/* ldr r1, =CONFIG_SYS_TEXT_BASE*/
/* call board_init_r */
ldr pc, =board_init_r /* this is auto-relocated! */ /* we should not return here. */
#endif ENDPROC(_main)

  再次编译运行,同时保存环境变量,并reset。

    

  已经运行正常了。

  reset后显示了一个错误,dm9000的地址未设置。下一节在修改,此时先看看env的启动流程。

2.2 env 的启动流程

  uboot中env的整个架构可以分为3层:  

  (1) 命令层,如saveenv,setenv editenv这些命令的实现,还有如启动时调用的env_relocate函数。

  (2) 中间封装层,利用不同静态存储器特性封装出命令层需要使用的一些通用函数,如env_init,env_relocate_spec,saveenv这些函数。实现文件在common/env_xxx.c

  (3) 驱动层,实现不同静态存储器的读写擦等操作,这些是uboot下不同子系统都必须的。

2.2.1 env初始化

  首先在board_init_f中调用init_sequence的env_init,这个函数是不同存储器实现的函数,nand中的实现如下:

  

 int env_init(void)
{
gd->env_addr = (ulong)&default_environment[];  /* 调用环境变量数组 */
gd->env_valid = ;                  /* 设置env标志有效位为1 */
return ;
}

  env_init要早于静态存储器的初始化,所以无法进行env的读写,这里将gd中的env相关变量进行配置,默认设置env为valid。方便后面env_relocate函数进行真正的env从nand到ram的relocate。

2.2.2 initr_env

  继续执行,在board_init_r中执行 initr_ebv

 static int initr_env(void)
{
debug("start of initr_env \n");
/* initialize environment */
if (should_load_env())
env_relocate();
else
set_default_env(NULL); /* Initialize from environment */
load_addr = getenv_ulong("loadaddr", , load_addr);
return ;
}

  这是在所有存储器初始化完成后执行的。

  调用should_load_env:

 static int should_load_env(void)
{
return ;
}

  返回 1之后执行下一句 env_relocate。

  

 void env_relocate(void)
{
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
env_reloc();
env_htab.change_ok += gd->reloc_off;
#endif
if (gd->env_valid == ) {
#if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
/* Environment not changable */
debug("in of set_default_env \n");
set_default_env(NULL);
#else
bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
set_default_env("!bad CRC");
#endif
} else {
debug("in of env_relocate_spec() \n");
env_relocate_spec();
}
}

  由于我们的 gd->env_valid 再board_init_f 函数中已经设置为1,这里会执行到 env_relocate_spec 函数中去。

  CONFIG_ENV_OFFSET_REDUND此宏我们未设置,运行的代码就是如下:

 void env_relocate_spec(void)
{
#if !defined(ENV_IS_EMBEDDED)
int ret;
ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); ret = readenv(CONFIG_ENV_OFFSET, (u_char *)buf);
if (ret) {
set_default_env("!readenv() failed");
return;
} env_import(buf, );
debug("end 【nand】 of env_relocate_spec 2 \n");
#endif /* ! ENV_IS_EMBEDDED */
}

  env_import 输出环境变量信息,至此已经结束。

  

  

  

  

u-boot移植(十三)---代码修改---裁剪及环境变量 一的更多相关文章

  1. u-boot移植(十三)---代码修改---裁剪及环境变量 二

    一.错误处理 上一节遇到一个错误: print一下: 发现我们在jz2440.h中静态写的网络参数都没有写进去. dm9000 address not set. dm9000的地址未设置. 这里对应两 ...

  2. linux修改当前用户环境变量永久生效

    在linux环境中,修改当前用户环境变量,且永久生效的方法如下. 1,编辑~/.bash_profile文件 1 2 3 # Get the aliases and functions 4 if [ ...

  3. 如何快速有效的修改java的环境变量

    之前已经修改过jdk的环境变量,,,,在/etc/profile下,,, export JAVA_HOME=/usr/java/jdk1.7.0_67-cloudera export PATH=${J ...

  4. 在c代码中获取用户环境变量

    1 extern char ** environ 这是一个字符串数组,最后一个元素是null,即\0. 2 在代码中的使用方法 直接extern char **environ,然后 直接environ ...

  5. Linux目录终章,单用户模式修改密码、环境变量、第三方软件安装

    目录 今日内容概要 内容详细 解析映射文件 磁盘挂载文件 开机加载脚本 系统启动级别 使用单用户模式修改密码 变量加载文件 登录提示信息 第三方软件安装目录(编译安装目录) 系统日志目录 保存系统运行 ...

  6. 代码修改shader Properties uniform变量

    2.4 Shader的数据接口:属性和 uniform变量     如果我们想设定一个特定的值到Shader,即为了在实例化Shader为Material时,可以通过为属性赋值达到创建具体对象的目的, ...

  7. java 代码中设置 临时 环境变量

    System.setProperty("hadoop.home.dir", "D:\\software\\software_install\\dev_install\\h ...

  8. 详解Windows不重启使环境变量修改生效(经典)

    在“我的电脑”->“属性”->“高级”->“环境变量”中增加或修改环境变量后,需重启系统才能使之生效.有没有什么方法可让它即时生效呢?下面介绍一种方法: 以修改环境变量“PATH”为 ...

  9. Ubuntu 12 修改环境变量

    Ubuntu Linux系统包含两类环境变量:系统环境变量和用户环境变量.系统环境变量对所有系统用户都有效,用户环境变量仅仅对当前的用户有效. 修改用户环境变量 用户环境变量通常被存储在下面的文件中: ...

随机推荐

  1. 操作系统+编程语言的分类+执行python程序的两种方式+变量

    1.什么是操作系统? 操作系统就是一个协调\管理\控制计算机硬件资源与软件资源的一个控制程序. 2.为何要操作系统? a.把复杂的硬件操作封装成简单的功能\接口用来给用户或者程序来使用(文件) b.把 ...

  2. 构建squid代理服务器

    基本概念 本文使用squid代理服务 软件介绍:百度百科 作为应用层的代理服务软件,Squid主要提供缓存加速.应用层过滤控制的功能: 工作机制:缓存网页对象,减少重复请求(HTTP代理的缓存加速对象 ...

  3. python 模块之-logging

    python  模块logging import logging ###  简单使用格式    日志级别等级CRITICAL > ERROR > WARNING > INFO > ...

  4. POJ1905-Expanding Rods-二分答案

    一根细棒升温时会变长,在两面墙中间,会变成一个弓形. 给出变长后的长度,求新的细棒中心与没伸长时的中心的距离. 简单的数学推导后就可以二分答案了,一开始没完全掌握二分的姿势,wa了好多.而且poj d ...

  5. python成长之路五-文件操作

    1,文件操作 f = open("D:\种子.txt",encoding="utf-8",mode="r") # 打开一个种子.txt文件, ...

  6. Codeforces976E Well played! 【贪心】

    题目分析: 由于乘二的收获很大,所以我们可以证明乘的数一定是同一个,接着排序后依次选取,判断一下即可. 题目代码: #include<bits/stdc++.h> using namesp ...

  7. matplotlib极坐标方法详解

    一.极坐标 在平面内取一个定点O,叫极点,引一条射线Ox,叫做极轴,再选定一个长度单位和角度的正方向(通常取逆时针方向).对于平面内任何一点M,用ρ表示线段OM的长度(有时也用r表示),θ表示从Ox到 ...

  8. 【BZOJ4712】洪水(动态dp)

    [BZOJ4712]洪水(动态dp) 题面 BZOJ 然而是权限题QwQ,所以粘过来算了. Description 小A走到一个山脚下,准备给自己造一个小屋.这时候,小A的朋友(op,又叫管理员)打开 ...

  9. 【BZOJ2003】[HNOI2010]矩阵(搜索)

    [BZOJ2003][HNOI2010]矩阵(搜索) 题面 懒得粘了,不难找吧. 题解 看的学长写的题解,也懒得写了 大概是这样的. 不难发现只需要确定第一行和第一列就能确定答案,而确定第一行之后每确 ...

  10. Internet Explorer 10 administration IE10管理

    http://4sysops.com/archives/internet-explorer-10-administration-part-1-overview/ http://4sysops.com/ ...