[RK1108][Linux3.1]調試筆記-分區表的修改

平臺 內核版本
RK1108 Linux3.1

實踐

查看當前設備分區表

命令cat /proc/partitions
在這裏插入圖片描述
kernel爲例,其大小爲8192KB/1024 = 8MB 。
那麼上面這個大小是哪裏設置,看下面。

修改配置文件

目錄:build/setting.ini
文件中關鍵的解釋如下:

意義
name 分區名
Type 類型:0x1:Vendor, 0x2:IDBlock, 0x4:Kernel, 0x8:boot, 0x80000000:data
Partoffset 偏移地址
PartSize 分區大小
Flag 1:skip flag, 2:reserved flag, 4:no partition size flag
File 文件目錄

其中Flag詳細解釋爲:

a.written partition file and fill up to partition size
Flag=
File=partition file

b.partition be filled up to partition size
Flag=0x2
File=/*do not set*/

c.skip,none of data be written to partition
Flag=0x1
File=/*do not set*/

d.last partition,partition size be set at runtime,alloc all of remain flash to it
Flag=0x4
File=/*set file as required*/

setting.ini詳細內容如下:

#Flag 1:skip flag, 2:reserved flag, 4:no partition size flag
#type 0x1:Vendor, 0x2:IDBlock, 0x4:Kernel, 0x8:boot, 0x80000000:data
#PartSize and PartOffset unit by sector
#Gpt_Enable 1:compact gpt, 0:normal gpt
#Backup_Partition_Enable 0:no backup,1:backup
#FILL_BYTE's value is used to fill blank
[System]
FwVersion=15.48.1
Gpt_Enable=
Backup_Partition_Enable=0
Nano=
[UserPart1]
Name=IDBlock
Type=0x2
PartOffset=0x40
PartSize=0x380
Flag=0x0
File=../rockimg/Image-cvr/rv1108ddr.bin,../rockimg/Image-cvr/rv1108loader.bin
[UserPart2]
Name=kernel
Type=0x4
PartOffset=0x400
PartSize=0x4000
Flag=0x0
File=../rockimg/Image-cvr/kernel.img
[UserPart3]
Name=rootfs
Type=0x8
PartOffset=0x4400
PartSize=0x10000
Flag=0x0
File=../rockimg/Image-cvr/rootfs.img
[UserPart4]
Name=recovery
Type=0x10
PartOffset=0x14400
PartSize=0x4000
Flag=0x0
File=../rockimg/Image-cvr/kernel.img
[UserPart5]
Name=storage
Type=0x80000000
PartOffset=0x18400
PartSize=0x1B800
Flag=0x0
File=../common/storage.img

文件中PartOffset通過前面分區表的偏移地址+分區大小得出。

kernel分區爲例:分區大小爲0x400、十進制轉換爲16384、大小爲16384/1024/2 = 8M,可以和我們上面cat /proc/partitions讀到的分區大小對上了。

上面還有一部分system沒有解釋:

  1. set format of firmware
Gpt_Enable= /*flat rk firmware*/
Gpt_Enable=0 /*flat gpt firmware*/
Gpt_Enable=1 /*compact gpt firmware*/
  1. backup header of firmware or not
Backup_Partition_Enable=1 /*backup firmware header*/
Backup_Partition_Enable= /*default,no backup firmware header,when you don't know flash size,no backup*/

注意
上面的storage分區需要根據分區表大小去製作。
目錄:config/Makefile

#TODO: compare the img size with the setting in setting.ini
#$(Q)make_ext4fs -l 62914560 $(RV_TOPDIR)/common/storage.img $(RV_TOPDIR)/common/storage
firmware-gen fwg fw: pack-kernel pack-rootfs
        @$(call MESSAGE,"Package Firmware.img")
        $(Q)cp $(KERNEL_PKGDIR)/kernel.img $(OUT_IMAGE_DIR)
        $(Q)cp $(RV_TOPDIR)/rockimg/Image-release/rv1108loader.bin $(OUT_IMAGE_DIR)
        $(Q)cp $(RV_TOPDIR)/rockimg/Image-release/rv1108ddr.bin $(OUT_IMAGE_DIR)
        $(Q)make_ext4fs -l 57671680 $(RV_TOPDIR)/common/storage.img $(RV_TOPDIR)/common/storage
        $(Q)$(RV_TOPDIR)/build/firmwareMerger -p $(RV_TOPDIR)/build/setting.ini $(OUT_IMAGE_DIR)/

其中storage分區是系統默認添加的分區,後面博客會介紹如何添加一個新的分區。

操作設備節點方式改寫

節點名:/dev/fw_header_p
驅動程序路徑:kernel/drivers/rkflash$ vim rkflash_blk.c,若此方式操作失敗需確認驅動是否加載。

程序:

頭文件

//ota
#include <stdio.h>
#include <string.h>

#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <pwd.h>
#include <errno.h>
#include <signal.h>
#include <linux/watchdog.h>
#include <linux/reboot.h>
#include <time.h>

結構體

typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#define RK_PARTITION_TAG (0x50464B52)

typedef enum {
    PART_VENDOR = 1 << 0,
    PART_IDBLOCK = 1 << 1,
    PART_KERNEL = 1 << 2,
    PART_BOOT = 1 << 3,
    PART_RECOVERY = 1 << 4,
    PART_DTB = 1 << 5,
    PART_UBOOT = 1 << 6,
    PART_USER = 1 << 31
} enum_parttion_type;

typedef struct {
    uint16  year;
    uint8   month;
    uint8   day;
    uint8   hour;
    uint8   min;
    uint8   sec;
    uint8   reserve;
} struct_datetime, *pstruct_datetime;

typedef struct {
    uint32  uiFwTag; //"RKFP"
    struct_datetime dtReleaseDataTime;
    uint32  uiFwVer;
    uint32  uiSize;//size of sturct,unit of uint8
    uint32  uiPartEntryOffset;//unit of sector
    uint32  uiBackupPartEntryOffset;
    uint32  uiPartEntrySize;//unit of uint8
    uint32  uiPartEntryCount;
    uint32  uiFwSize;//unit of uint8
    uint8   reserved[464];
    uint32  uiPartEntryCrc;
    uint32  uiHeaderCrc;
} struct_fw_header, *pstruct_fw_header;

typedef struct {
    uint8   szName[32];
    enum_parttion_type emPartType;
    uint32  uiPartOffset;//unit of sector
    uint32  uiPartSize;//unit of sector
    uint32  uiDataLength;//unit of uint8
    uint32  uiPartProperty;
    uint8   reserved[76];
} struct_part_entry, *pstruct_part_entry;

typedef struct {
    struct_fw_header hdr;     //0.5KB
    struct_part_entry part[12]; //1.5KB
} struct_part_info, *pstruct_part_info;

#define FW_HEAD_DEV "/dev/fw_header_p"

操作函數

int getFwPartInfo(struct_part_info *Info)
{
    int imagefd;
	char imagepath[40];

    imagefd = open(FW_HEAD_DEV, O_RDONLY);
    if (imagefd < 0) {
        printf("Firmware open %s failed \n", FW_HEAD_DEV);
        return -1;
    }

    if (read(imagefd, Info, sizeof(struct_part_info)) <= 0) {
        printf("Firmware read %s failed \n", FW_HEAD_DEV);
        return -1;
    }

    if (Info->hdr.uiFwTag != RK_PARTITION_TAG) {
        printf("Firmware Tag error\n");
        return -1;
    }

    close(imagefd);
    return 0;
}

int debugFwPartInfo(struct_part_info *Info)
{
	int i;

    for (i = 0; i < Info->hdr.uiPartEntryCount; i++) {
		printf("Info.part[%d].szName 		%s\n", i, Info->part[i].szName);
		printf("Info.part[%d].emPartType 	%x\n", i, Info->part[i].emPartType);
		printf("Info.part[%d].uiPartOffset 	%x\n", i, Info->part[i].uiPartOffset);
		printf("Info.part[%d].uiPartSize 	%x\n", i, Info->part[i].uiPartSize);
		printf("Info.part[%d].uiDataLength 	%x\n", i, Info->part[i].uiDataLength);
		printf("Info.part[%d].uiPartProperty%x\n", i, Info->part[i].uiPartProperty);
    }
    return 0;
}

int setFwPartInfo(struct_part_info *Info)
{
    int imagefd;
	char imagepath[40];

    imagefd = open(FW_HEAD_DEV, O_RDWR);
    if (imagefd < 0) {
        printf("Firmware open %s failed \n", FW_HEAD_DEV);
        return -1;
    }

    if (write(imagefd, Info, sizeof(struct_part_info)) <= 0) {
        printf("Firmware write %s failed \n", FW_HEAD_DEV);
        return -1;
    }

    close(imagefd);
    return 0;
}

主程序操作

	struct_part_info Info;
	getFwPartInfo(&Info);
	debugFwPartInfo(&Info);
    Info.hdr.uiPartEntryCount = 6;
    
    memcpy(Info.part[4].szName, "recovery", 8);
    Info.part[4].emPartType    = 0x10;
    Info.part[4].uiPartOffset  = 0x14400;
    Info.part[4].uiPartSize    = 0x4000;
    Info.part[4].uiDataLength  = 0x51b514;

    memcpy(Info.part[5].szName, "storage", 8);
    Info.part[5].emPartType    = 0x80000000;
    Info.part[5].uiPartOffset  = 0x18400;
    Info.part[5].uiPartSize    = 0x1b800;
    Info.part[5].uiDataLength  = 0x3700000;

    setFwPartInfo(&Info);

    getFwPartInfo(&Info);
    debugFwPartInfo(&Info);
    
    if(access("/dev/recovery",F_OK)!=-1) {
    	printf("yang this dev recovery ok\n");
    	system("dd if=/dev/kernel of=/dev/recovery bs=1K");
    	system("busybox mkfs.ext2  /dev/storage");
    	system("busybox mount -t ext4 /dev/storage /mnt/storage");
    	system("sync");
    } else {
    	printf("yang this not have recovery\n");
    	printf("yang thsi is will be reboot\n");
   	 	system("reboot");
    }



思考

分區是打包到固件裏?

我們查找資料解釋如下:

firmware_merger read setting.ini to get partition info and create firmware.firmware_merger can generate 
three kinds of firmware(1.flat rk firmware 2.flat gpt firmware 3.compact gpt firmware).flat firmware can be
directly written into flash by 'wl'command.Compact firmware can only be written by productiontool. when SPL
is rk miniloader,firmware use flat rk format.when SPL is u-boot,firmware use flat gpt. 

大概意思就是 firmware_merger會讀取setting.ini
回顧之前的config/Makefile也可以發現:
Firmware有關:

        @echo 'Firmware:'
        @echo '  firmware-gen           - Generate firmware'
        @echo '  firmware-write         - Write firmware to board'

#TODO: compare the img size with the setting in setting.ini
#$(Q)make_ext4fs -l 62914560 $(RV_TOPDIR)/common/storage.img $(RV_TOPDIR)/common/storage
firmware-gen fwg fw: pack-kernel pack-rootfs
        @$(call MESSAGE,"Package Firmware.img")
        $(Q)cp $(KERNEL_PKGDIR)/kernel.img $(OUT_IMAGE_DIR)
        $(Q)cp $(RV_TOPDIR)/rockimg/Image-release/rv1108loader.bin $(OUT_IMAGE_DIR)
        $(Q)cp $(RV_TOPDIR)/rockimg/Image-release/rv1108ddr.bin $(OUT_IMAGE_DIR)
        $(Q)make_ext4fs -l 57671680 $(RV_TOPDIR)/common/storage.img $(RV_TOPDIR)/common/storage
        $(Q)$(RV_TOPDIR)/build/firmwareMerger -p $(RV_TOPDIR)/build/setting.ini $(OUT_IMAGE_DIR)/

firmware-gen->target-post-image

target-post-image: prepare prepare-rootfs target-finalize firmware-gen
        @$(foreach s, $(call qstrip,$(RV_ROOTFS_POST_IMAGE_SCRIPT)), \
                $(call MESSAGE,"Executing post-image script $(s)"); \
                $(EXTRA_ENV) $(s) $(BINARIES_DIR) $(call qstrip,$(RV_ROOTFS_POST_SCRIPT_ARGS))$(sep))

其中:world: target-post-image

        @echo 'Build:'
        @echo '  all                    - make world'

因此在make all 或者 make fw會重新讀取setting.ini

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章