mkv210_image.c详解
1.背景知識回顧
s5pv210啟動后先執行內部iROM中的BL0,BL0執行完后會根據OMpin的配置選擇一個外部設備來啟動(有很多,我們實際使用的有2個:usb啟動和SD卡啟動)。?
在usb啟動時,內部BL0讀取到BL1后不做校驗,直接從BL1的實質內部0xd0020010開始執行,因此usb啟動的景象led.bin不需要頭信息,因此我們從usb啟動時直接將鏡像下載到0xd0020010去執行即可,不管頭信息了。?
從SD啟動時,BL0會首先讀取sd卡得到完整的鏡像(完整指的是led.bin和16字節的頭),然后BL0會自己根據你的實際鏡像(指led.bin)來計算一個校驗和checksum,然后和你完整鏡像的頭部中的checksum來比對。如果對應則執行BL1,如果不對應則啟動失敗(會轉入執行2st啟動,即SD2啟動。如果這里已經是2st啟動了,這里校驗通不過就死定了)。(一開始計算出來的(之后被存儲在頭部16字節中),和BL0從sd卡讀取出來后重新計算的(可能由SD卡于機械特性出現錯誤),進行對比)
2、mkv210_image.c的作用
保證文件小于16k,并為BL1添加校驗頭。編譯鏈接時只得到led.bin,由led.bin得到210.bin的過程是三星的S5PV210所特有的,因此需要我們自己去完成,為此我們寫了mkv210_image.c來完成。
?
3、代碼詳解?
第1步:檢驗用戶傳參是不是3個。
第2步:分配16K Bbuffer并且填充為0.
第3步: 讀源bin到buffer(過程:打開源bin,獲取源bin長度,源bin長度不得超過16K-16byte,將源bin放入事先已經填充過的buffer[16]中,關閉源bin)
第4步: 計算校驗和(在要校驗的內存區域中,所有內存中的內容按照字節為單位來進行相加,最終相加的和與整鏡像的頭部中的checksum來比對)
第5步:拷貝buffer中的內容到目的bin,即完成由led.bin得到210.bin。
(1)main函數兩個形參的作用?
main函數接收2個形參:argc和argv。?
argc是用戶(通過命令行來)執行這個程序時,實際傳遞的參數個數。注意這個個數是包含程序執行本身的?
argv是一個字符串數組,這個數組中存儲的字符串就是一個個的傳參。?
譬如我們執行程序時使用./mkx210 led.bin 210.bin,則argc = 3,則argv[0] = “./mkx210” argv[1] = led.bin argv[2] = 210.bin?
(2)glibc讀寫文件接口?
linux中要讀取一個文件,可以使用fopen打開文件,fread讀取文件,讀完之后fclose關閉文件。?
要寫文件用fwrite來寫。這些函數是glibc的庫函數,在linux中用man 3 可以查找。?
(3)校驗和的計算方法?
校驗和其實就是需要校驗的內存區域中,所有內存中的內容按照字節為單位來進行相加,最終相加的和極為校驗和。
/*
?* mkv210_image.c作用:將usb啟動時使用的xxx_usb.bin制作得到由sd卡啟動的鏡像xxx_sd.bin
?* 本文件來自于友善之臂的裸機教程,據友善之臂的文檔中講述,本文件是一個熱心網友提供,在此表示感謝。
?*
?* 在BL0階段,Irom內固化的代碼讀取nandflash或SD卡前16K的內容,
?* 并比對前16字節中的校驗和是否正確,正確則繼續,錯誤則停止。
?*/
#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字節,隨便16個字節即可
int main (int argc, char *argv[])
{
? ? FILE *fp;
? ? char *Buf, *a;
? ? int BufLen;
? ? int nbytes, fileLen;
? ? unsigned int checksum, count;
? ? int i;
? ? // 1.檢查參數個數是否為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,
? ? // 注意若裸機程序大于16KB,則裸機程序會出問題,在后續做LCD實驗時需特別注意
? ? 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.計算校驗和
? ? // 4.1從第16byte開始計算,把buffer中所有的字節數據加和起來得到的結果
? ? a = Buf + SPL_HEADER_SIZE;
? ? for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)
? ? ? ? checksum += (0x000000FF) & *a++;
? ? // 4.2將校驗和保存在buffer[8~12]
? ? a = Buf + 8; ? ?// Buf是xxx_sd.bin的起始地址,+8表示向后位移2個字,也就是說寫入到第3個字
? ? *((unsigned int *)a) = checksum;
? ? // 5.拷貝buffer中的內容到目的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;
}
總結
以上是生活随笔為你收集整理的mkv210_image.c详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uboot之源码目录分析
- 下一篇: 华为服务器euleros系统,euler