mkv210_image.c详解
1.背景知識回顧
s5pv210啟動后先執(zhí)行內(nèi)部iROM中的BL0,BL0執(zhí)行完后會根據(jù)OMpin的配置選擇一個(gè)外部設(shè)備來啟動(有很多,我們實(shí)際使用的有2個(gè):usb啟動和SD卡啟動)。?
在usb啟動時(shí),內(nèi)部BL0讀取到BL1后不做校驗(yàn),直接從BL1的實(shí)質(zhì)內(nèi)部0xd0020010開始執(zhí)行,因此usb啟動的景象led.bin不需要頭信息,因此我們從usb啟動時(shí)直接將鏡像下載到0xd0020010去執(zhí)行即可,不管頭信息了。?
從SD啟動時(shí),BL0會首先讀取sd卡得到完整的鏡像(完整指的是led.bin和16字節(jié)的頭),然后BL0會自己根據(jù)你的實(shí)際鏡像(指led.bin)來計(jì)算一個(gè)校驗(yàn)和checksum,然后和你完整鏡像的頭部中的checksum來比對。如果對應(yīng)則執(zhí)行BL1,如果不對應(yīng)則啟動失敗(會轉(zhuǎn)入執(zhí)行2st啟動,即SD2啟動。如果這里已經(jīng)是2st啟動了,這里校驗(yàn)通不過就死定了)。(一開始計(jì)算出來的(之后被存儲在頭部16字節(jié)中),和BL0從sd卡讀取出來后重新計(jì)算的(可能由SD卡于機(jī)械特性出現(xiàn)錯(cuò)誤),進(jìn)行對比)
2、mkv210_image.c的作用
保證文件小于16k,并為BL1添加校驗(yàn)頭。編譯鏈接時(shí)只得到led.bin,由led.bin得到210.bin的過程是三星的S5PV210所特有的,因此需要我們自己去完成,為此我們寫了mkv210_image.c來完成。
?
3、代碼詳解?
第1步:檢驗(yàn)用戶傳參是不是3個(gè)。
第2步:分配16K Bbuffer并且填充為0.
第3步: 讀源bin到buffer(過程:打開源bin,獲取源bin長度,源bin長度不得超過16K-16byte,將源bin放入事先已經(jīng)填充過的buffer[16]中,關(guān)閉源bin)
第4步: 計(jì)算校驗(yàn)和(在要校驗(yàn)的內(nèi)存區(qū)域中,所有內(nèi)存中的內(nèi)容按照字節(jié)為單位來進(jìn)行相加,最終相加的和與整鏡像的頭部中的checksum來比對)
第5步:拷貝buffer中的內(nèi)容到目的bin,即完成由led.bin得到210.bin。
(1)main函數(shù)兩個(gè)形參的作用?
main函數(shù)接收2個(gè)形參:argc和argv。?
argc是用戶(通過命令行來)執(zhí)行這個(gè)程序時(shí),實(shí)際傳遞的參數(shù)個(gè)數(shù)。注意這個(gè)個(gè)數(shù)是包含程序執(zhí)行本身的?
argv是一個(gè)字符串?dāng)?shù)組,這個(gè)數(shù)組中存儲的字符串就是一個(gè)個(gè)的傳參。?
譬如我們執(zhí)行程序時(shí)使用./mkx210 led.bin 210.bin,則argc = 3,則argv[0] = “./mkx210” argv[1] = led.bin argv[2] = 210.bin?
(2)glibc讀寫文件接口?
linux中要讀取一個(gè)文件,可以使用fopen打開文件,fread讀取文件,讀完之后fclose關(guān)閉文件。?
要寫文件用fwrite來寫。這些函數(shù)是glibc的庫函數(shù),在linux中用man 3 可以查找。?
(3)校驗(yàn)和的計(jì)算方法?
校驗(yàn)和其實(shí)就是需要校驗(yàn)的內(nèi)存區(qū)域中,所有內(nèi)存中的內(nèi)容按照字節(jié)為單位來進(jìn)行相加,最終相加的和極為校驗(yàn)和。
/*
?* mkv210_image.c作用:將usb啟動時(shí)使用的xxx_usb.bin制作得到由sd卡啟動的鏡像xxx_sd.bin
?* 本文件來自于友善之臂的裸機(jī)教程,據(jù)友善之臂的文檔中講述,本文件是一個(gè)熱心網(wǎng)友提供,在此表示感謝。
?*
?* 在BL0階段,Irom內(nèi)固化的代碼讀取nandflash或SD卡前16K的內(nèi)容,
?* 并比對前16字節(jié)中的校驗(yàn)和是否正確,正確則繼續(xù),錯(cuò)誤則停止。
?*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFSIZE ? ? ? ? ? ? ? ? (16*1024)
#define IMG_SIZE ? ? ? ? ? ? ? ?(16*1024)
#define SPL_HEADER_SIZE ? ? ? ? 16
#define SPL_HEADER ? ? ? ? ? ?"S5PC110 HEADER ?" ? ?// 16字節(jié),隨便16個(gè)字節(jié)即可
int main (int argc, char *argv[])
{
? ? FILE *fp;
? ? char *Buf, *a;
? ? int BufLen;
? ? int nbytes, fileLen;
? ? unsigned int checksum, count;
? ? int i;
? ? // 1.檢查參數(shù)個(gè)數(shù)是否為3
? ? if (argc != 3)
? ? {
? ? ? ? printf("Usage: %s <source file> <destination file>\n", argv[0]);
? ? ? ? return -1;
? ? }
? ? // 2.分配16K的buffer并請零
? ? BufLen = BUFSIZE;
? ? Buf = (char *)malloc(BufLen);
? ? if (!Buf)
? ? {
? ? ? ? printf("malloc buffer failed!\n");
? ? ? ? return -1;
? ? }
? ? memset(Buf, 0x00, BufLen);
? ? // 3.讀源bin到buffer
? ? // 3.1 打開源bin
? ? fp = fopen(argv[1], "rb");
? ? if( fp == NULL)
? ? {
? ? ? ? printf("source file open error\n");
? ? ? ? free(Buf);
? ? ? ? return -1;
? ? }
? ? // 3.2獲取源bin長度
? ? fseek(fp, 0L, SEEK_END); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 定位到文件尾
? ? fileLen = ftell(fp); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 得到文件長度
? ? fseek(fp, 0L, SEEK_SET); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 再次定位到文件頭
? ? // 3.3源bin長度不得超過16K-16byte,
? ? // 注意若裸機(jī)程序大于16KB,則裸機(jī)程序會出問題,在后續(xù)做LCD實(shí)驗(yàn)時(shí)需特別注意
? ? count = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))
? ? ? ? ? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);
? ? // 3.4在buffer[0~15]中存放"S5PC110 HEADER ?"
? ? memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE);
? ? // 3.5讀源bin到buffer[16]
? ? nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp);
? ? if ( nbytes != count )
? ? {
? ? ? ? printf("source file read error\n");
? ? ? ? free(Buf);
? ? ? ? fclose(fp);
? ? ? ? return -1;
? ? }
? ? fclose(fp);
? ? // 4.計(jì)算校驗(yàn)和
? ? // 4.1從第16byte開始計(jì)算,把buffer中所有的字節(jié)數(shù)據(jù)加和起來得到的結(jié)果
? ? a = Buf + SPL_HEADER_SIZE;
? ? for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)
? ? ? ? checksum += (0x000000FF) & *a++;
? ? // 4.2將校驗(yàn)和保存在buffer[8~12]
? ? a = Buf + 8; ? ?// Buf是xxx_sd.bin的起始地址,+8表示向后位移2個(gè)字,也就是說寫入到第3個(gè)字
? ? *((unsigned int *)a) = checksum;
? ? // 5.拷貝buffer中的內(nèi)容到目的bin
? ? // 5.1打開目的bin
? ? fp = fopen(argv[2], "wb");
? ? if (fp == NULL)
? ? {
? ? ? ? printf("destination file open error\n");
? ? ? ? free(Buf);
? ? ? ? return -1;
? ? }
? ? // 5.2將16k的buffer拷貝到目的bin中
? ? a = Buf;
? ? nbytes = fwrite(a, 1, BufLen, fp);
? ? if (nbytes != BufLen)
? ? {
? ? ? ? printf("destination file write error\n");
? ? ? ? free(Buf);
? ? ? ? fclose(fp);
? ? ? ? return -1;
? ? }
? ? free(Buf);
? ? fclose(fp);
? ? return 0;
}
總結(jié)
以上是生活随笔為你收集整理的mkv210_image.c详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uboot之源码目录分析
- 下一篇: STM32之ADC单通道连续例程