.自动生成升级包
sh ./host/package_generate.sh ~/apollo/sw/ga300/target/output/flash_bin/systems/huangpu-summit-dualhd-gnu-4.4.0-linux-debug/
该命令生成一个文件和一个目录,依赖于当前时间,比如:
apollo-sw-2010-11-10-15-04_dir\: 拷贝到u盘根目录即可被升级程序识别
apollo-sw-2010-11-10-15-04:  上述目录的squashfs包,应用于网络下载升级

升级程序启动后,将读取网络分区和u盘,查找apollo-sw开头的目录或者升级包,如果文件或目录名比当前版本字串更大,则运行升级包里的autorun.sh执行升级。
更全面的信息建议阅读:<<Apollo 升级系统——需求分析+概要设计>>

.升级包结构
升级包包括一个autorun.sh和需要引用的文件。升级的实现即通过运行autorun.sh来实现。
比如下面一个简单的autorun.sh:
p_w_picpath_update -d /dev/mtd5 -m linux-2.6.28.10/vmlinux.bin -c 2963891368 -l  4685120
p_w_picpath_update -d /dev/mtd7 -m appfs.jffs2.nand -c 1085098658 -l  22550628
p_w_picpath_update -d /dev/mtd6 -m rootfs.arm.jffs2.nand -c 664852602 -l  3521352

那么升级包还应该包括linux-2.6.28.10/vmlinux.bin,appfs.jffs2.nand,rootfs.arm.jffs2.nand。
升级的结果即把这些文件写道相应的分区中。

升级程序启动后读取升级包里的autorun.sh并且运行,这种设计可以实现各种灵活的应用,用户可以在升级包里包含自己的程序。
比如运行不同的升级界面,或者执行网络升级。

.生成升级映像
Step 1: 生成rootfs
#cd upgrade/target
#sh build_upgrade_p_w_picpath.sh

Step 2: 生成p_w_picpath
make -C $KSRC O=$KERNEL_OBJ_DIR menuconfig
使得
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="/home/qianjiang/tmp/qjbackup/upgrade/target/outputn/rootfs.tmplt"  #绝对路径
CONFIG_APOLLO_SPLASH is not set              #关闭splash
CONFIG_LOGO is not set                       #不需要开机logo
CONFIG_NTFS_FS=y                             #打开ntfs读支持
生成的config可以保留,将来直接替换即可。
生成的vmlinux.bin即升级映像

需要考虑的另外一个映像是uboot env映像,生成工具见:
./host/generate_env_p_w_picpath


.移植
不同的项目分区不一样,所以移植主要的任务是确定mtdparts. 比如:
mtdparts=nx_2017:1m@0k(uldr),512k@1m(uboot),512k@1536k(env),10m@2m(update),6m@12m(kernel),12m@18m(root),200m@30m(appfs),200m@230m(net),30m@430m(user1),30m@430m(user2),22m@490m(reserve)
注意:必须有env分区。


.理解升级系统的实现方法
文件target/src/etc/S50update.sh,即实现的概要,下面简述之:
-------------------------------------------------------
insmod /usr/fb_device.ko                        #安装framebuffer驱动
upgrade_osd &                                   #运行显示程序
automount > /tmp/upgrade_msg                    #挂载U盘的分区,并且把运行结果输出到管道文件upgrade_msg,该管道的读取方是upgrade_osd,显示内容到屏幕
perform_mount=$(find_update_package /tmp/media) #/tmp/media下面挂载了U盘的分区,find_update_package到该分区下面查找可以升级的软件包

#下面切换到升级包目录
if [ ${perform_mount:0:2} = "cd" ]; then
    $perform_mount
elif [ ${perform_mount:0:5} = "mount" ]; then
    $perform_mount
else
    echo "No upgrade package" > /tmp/upgrade_msg
    echo $fail_msg > /tmp/upgrade_msg
    exit
fi

#如果升级目录下面存在autorun.sh,则运行autorun.sh
if [ ! -x autorun.sh ]; then
    echo Invalid upgrade package: $sw_package_version_str > /tmp/upgrade_msg
    echo $fail_msg > /tmp/upgrade_msg
    exit
fi

./autorun.sh



.目录结构,文件功能描述
1. host
该目录存放相关运行于PC端的一些工具
env.txt:uboot环境变量组织模板,不同客户有不同定制
package_generate.sh:升级包生成工具,不同客户有不同定制
set_uboot_env:expect脚本,可以和uboot交互自动更新环境变量

./host/generate_env_p_w_picpath:
    generate_env_p_w_picpath.sh:读取env.txt生成env p_w_picpath
    uboot_env: PC端env读写工具

2. target
build_upgrade_p_w_picpath.sh:编译升级系统

./target/overlay-elgakingdom
    linuxkernel.config.patch:编译内核时需要使用的配置
    nand.c:适应于elgakingdom的nand驱动

./target/overlay-skyworth:
    patch/:针对sky板子的配置
    build_skyworth:记录编译sky工程的方法
    env.txt:适应于sky项目的环境设置
    p_w_picpaths/:里面的映像文件联系起来烧录到nand,启动后就支持升级
    linuxkernel.config.patch:编译内核时,需要使用的配置

2.1 target/src
  automount.c: 自动挂载U盘分区到文件系统
  fbdevice/ : framebuffer驱动
  find_update_package.c: 查找升级包
  p_w_picpath_update/:更新mtd分区的程序
  uboot_env/: 支持对env分区的读写等
  upgrade_osd/:显示升级相关信息
  etc/:升级系统启动脚本


.TODO:
1. 开发一个升级包,里面的工具可以读取nand里面的映像,包括ecc信息。这样可以应用于烧录器(如果没有找到ecc生成算法)。
2. 支持热拔插。比如升级失败,用户可以修改升级包然后重新插入,将自动升级
3. 减少升级映像size,比如通过内核的压缩,或者内核映像的定制(比如去掉网络)。
4. 支持通过uldr装入升级映像,运行。这样可以执行升级。
5. p_w_picpath_update对坏块的管理是skip bad block,没有使用bbt。是否有问题,需要验证?
6. uboot默认的分区大小是512k,对于large page的nand,一个block即256K。所以uboot分区应该加大,允许出现坏块。
7. 实现kernel console,程序执行的输出显示到屏幕。定制console driver,以便支持进度条和状态显示。
   可以参考:
   <<Essential Linux Divice Drivers>>, http://en.gentoo-wiki.com/wiki/Initramfs
8. 大文件,比如30M,如果制作在squashfs中,可能带来问题,原因未名。估计和内存有关(因为mount到loop0),如果写道mtd中可能没问题。所以这个时候建议用目录的方式拷贝到U盘。
9. fbdevice,mmap还没搞定。现在通过write系统调用实现。