日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux分区表与uboot,Linux和Uboot下eMMC boot分区读写

發(fā)布時間:2023/12/19 linux 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux分区表与uboot,Linux和Uboot下eMMC boot分区读写 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

關(guān)鍵詞:eMMC boot、PARTITION_CONFIG、force_ro等。

1. eMMC的分區(qū)

大部分eMMC都有類似如下的分區(qū),其中BOOT、RPMB和UDA一般是默認(rèn)存在的,gpp分區(qū)需要手動創(chuàng)建。

BOOT主要是為了支持從eMMC啟動系統(tǒng)而設(shè)計的;RPMB即Replay Protected Memory Block簡稱,通常用來保存安全線管的數(shù)據(jù);GPP主要用于存儲系統(tǒng)或者用戶數(shù)據(jù)。

UDA通常會進(jìn)行再分區(qū),然后根據(jù)不同目的存放相關(guān)數(shù)據(jù),或者格式化成不同文件系統(tǒng)。

2. Linux下讀寫boot分區(qū)

因為boot分區(qū)中一般存放的是bootloader或者相關(guān)配置參數(shù),這些參數(shù)一般是不允許修改的,所以默認(rèn)情況下是能讀boot分區(qū),不能寫。

2.1 使能讀寫

如果需要些則需要,修改/sys/block/mmcblk0boot1/force_ro。

使能寫:

echo 0 > /sys/block/mmcblk0boot1/force_ro

關(guān)閉寫:

echo 1 > /sys/block/mmcblk0boot1/force_ro

在重啟之后,force_ro會恢復(fù)為1。

2.2 內(nèi)核force_ro實現(xiàn)

下面來看看force_ro是如何起作用的?

eMMC在被初始化的時候,調(diào)用mmc_blk_probe(),這里面會在每個設(shè)備下創(chuàng)建force_ro sysfs節(jié)點。

static int mmc_blk_probe(struct mmc_card *card)

{

...

if (mmc_add_disk(md))

goto out;

...

}

static int mmc_add_disk(struct mmc_blk_data *md)

{

int ret;

struct mmc_card *card = md->queue.card;

device_add_disk(md->parent, md->disk);

md->force_ro.show = force_ro_show;

md->force_ro.store = force_ro_store;----------------------------------------------設(shè)置分區(qū)是否只讀,0可讀寫;1只讀。

sysfs_attr_init(&md->force_ro.attr);

md->force_ro.attr.name = "force_ro";

md->force_ro.attr.mode = S_IRUGO | S_IWUSR;

ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);

if (ret)

goto force_ro_fail;

if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&

card->ext_csd.boot_ro_lockable) {

umode_t mode;

if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)

mode = S_IRUGO;

else

mode = S_IRUGO | S_IWUSR;

md->power_ro_lock.show = power_ro_lock_show;

md->power_ro_lock.store = power_ro_lock_store;

sysfs_attr_init(&md->power_ro_lock.attr);

md->power_ro_lock.attr.mode = mode;

md->power_ro_lock.attr.name =

"ro_lock_until_next_power_on";

ret = device_create_file(disk_to_dev(md->disk),

&md->power_ro_lock);

if (ret)

goto power_ro_lock_fail;

}

return ret;

power_ro_lock_fail:

device_remove_file(disk_to_dev(md->disk), &md->force_ro);

force_ro_fail:

del_gendisk(md->disk);

return ret;

}

static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,

char *buf)

{

int ret;

struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));

ret = snprintf(buf, PAGE_SIZE, "%d/n",

get_disk_ro(dev_to_disk(dev)) ^

md->read_only);

mmc_blk_put(md);

return ret;

}

static ssize_t force_ro_store(struct device *dev, struct device_attribute *attr,

const char *buf, size_t count)

{

int ret;

char *end;

struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));

unsigned long set = simple_strtoul(buf, &end, 0);

if (end == buf) {

ret = -EINVAL;

goto out;

}

set_disk_ro(dev_to_disk(dev), set || md->read_only);

ret = count;

out:

mmc_blk_put(md);

return ret;

}

2.3 讀寫boot分區(qū)操作

在force_ro為1的情況下,寫boot分區(qū)返回Operation not permitted。

echo updt | dd of=/dev/mmcblk0boot1 bs=4 count=1 seek=0 && sync

dd: writing '/dev/mmcblk0boot1': Operation not permitted

1+0 records in

0+0 records out

然后打開force_ro=0:

echo 0 > /sys/block/mmcblk0boot1/force_ro && echo updt | dd of=/dev/mmcblk0boot1 bs=4 count=1 seek=0 && sync

通過hexdump驗證一下:

hexdump -v -n 4 -s 0 /dev/mmcblk0boot1

0000000 7075 7464

0000004

3. uboot下讀寫boot分區(qū)

uboot下操作boot分區(qū)需要打開CONFIG_SUPPORT_EMMC_BOOT。

在Linux下/dev/mmcblk0boot1就表示切換到boot分區(qū)了,在uboot下需要先切換到boot分區(qū)。

3.1 PARTITION_CONFIG寄存器

由于默認(rèn)分區(qū)是UDA,而eMMC每個分區(qū)都是獨(dú)立編址的。所以要使用boot分區(qū)需要切換分區(qū)。

PARTITION_CONFIG寄存器,通過EXT_CSD_PART_CONF命令來設(shè)置。

根據(jù)下面的寄存解釋,BOOT_ACK設(shè)置為0x0,;BOOT_PARTITION_ENABLE設(shè)置為0x2;PARTITION_ACCESS設(shè)置為0x2。

3.2 讀取boot分區(qū)

uboot中讀取boot分區(qū),首先需要將分區(qū)切換到boot分區(qū),然后讀寫分區(qū),最后將分區(qū)切換回原來分區(qū)。

static int do_mmc_bootmode(cmd_tbl_t *cmdtp, int flag,

int argc, char * const argv[])

{

struct mmc *mmc;

int ret = BOOTMODE_NORMAL;

u32 blk, cnt, n;

void *addr;

char original_part;

addr = (void *)malloc(512);

blk = BOOTMODE_BLK_NUM;

cnt = BOOTMODE_BLK_COUNT;

mmc = init_mmc_device(curr_device, false);

if (!mmc)

{

free(addr);

return CMD_RET_FAILURE;

}

/* Switch to the Boot 2 partition */

original_part = mmc->block_dev.hwpart;

blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_BOOT2);

mmc_set_part_conf(mmc, 0, MMC_PART_BOOT2, 2);------------------------------------------切換到eMMC boot1分區(qū)。

n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);----------------------------------讀取一個block。

if(n != cnt)

{

free(addr);

return CMD_RET_FAILURE;

}

/* flush cache after read */

flush_cache((ulong)addr, cnt * 512); /* FIXME */

if(*(unsigned int *)addr == BOOTMODE_UPDATE_MAGIC)

{

ret = BOOTMODE_UPDATE;

}

else

{

ret = BOOTMODE_NORMAL;

}

#if 0

for(int i = 0; i < 512/16; i++)

printf("%08x %08x %08x %08x/n", *((int *)addr+i*4), *((int *)addr+i*4+1), *((int *)addr+i*4+2), *((int *)addr+i*4+3));

#endif

/* Switch to original partition. */

blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part);----------------------切換到默認(rèn)分區(qū)。

free(addr);

return ret;

}

至此可以在Linux和Uboot下對boot分區(qū)進(jìn)行操作,進(jìn)行bootloader燒寫或者進(jìn)行重要數(shù)據(jù)更新。

Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx

本文永久更新鏈接地址:https://www.linuxidc.com/Linux/2019-04/158316.htm

TAG:

除非注明,文章均由 Linux系統(tǒng)學(xué)習(xí) 整理發(fā)布,歡迎轉(zhuǎn)載。如有版權(quán)爭議,請聯(lián)系刪除。

總結(jié)

以上是生活随笔為你收集整理的linux分区表与uboot,Linux和Uboot下eMMC boot分区读写的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。