《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 設(shè)計應(yīng)用 > 嵌入式系統(tǒng)的 BootLoader的深入研究
嵌入式系統(tǒng)的 BootLoader的深入研究
摘要: 本文將從BootLoader的概念、BootLoader的主要任務(wù)、BootLoader的框架結(jié)構(gòu)以及BootLoader的安裝等四個方面來討論嵌入式系統(tǒng)的BootLoader。
Abstract:
Key words :

  一、簡介

  本文將從 BootLoader 的概念、BootLoader 的主要任務(wù)、BootLoader 的框架結(jié)構(gòu)以及 BootLoader 的安裝等四個方面來討論嵌入式系統(tǒng)的 BootLoader。

  引導(dǎo)加載程序 。包括固化在固件 (firmware) 中的 boot 代碼 ( 可選 ) ,和 Boot Loader 兩大部分。

  Linux 內(nèi)核 。特定于嵌入式板子的定制內(nèi)核以及內(nèi)核的啟動參數(shù)。

  引導(dǎo)加載程序是系統(tǒng)加電后運行的第一段軟件代碼。

  回憶一下 PC 的體系結(jié)構(gòu)我們可以知道,PC 機中的引導(dǎo)加載程序由 BIOS(其本質(zhì)就是一段固件程序)和位于硬盤 MBR 中的OS Boot Loader(比如,LILO 和GRUB 等)一起組成。BIOS 在完成硬件檢測和資源分配后,將硬盤 MBR 中的 Boot Loader 讀到系統(tǒng)的 RAM 中,然后將控制權(quán)交給 OS Boot Loader。Boot Loader 的主要運行任務(wù)就是將內(nèi)核映象從硬盤上讀到 RAM 中,然后跳轉(zhuǎn)到內(nèi)核的入口點去運行,也即開始啟動操作系統(tǒng)。而在嵌入式系統(tǒng)中,通常并沒有像 BIOS 那樣的固件程序(注,有的嵌入式 CPU 也會內(nèi)嵌一段短小的啟動程序),因此整個系統(tǒng)的加載啟動任務(wù)就完全由 Boot Loader 來完成。比如在一個基于 ARM7TDMI core 的嵌入式系統(tǒng)中,系統(tǒng)在上電或復(fù)位時通常都從地址0x00000000 處開始執(zhí)行,而在這個地址處安排的通常就是系統(tǒng)的 Boot Loader 程序。

 

  二、Boot Loader 的概念

 

  簡單地說,Boot Loader 就是在操作系統(tǒng)內(nèi)核運行之前運行的一段小程序。通過這段小程序,我們可以初始化硬件設(shè)備、建立內(nèi)存空間的映射圖,從而將系統(tǒng)的軟硬件環(huán)境帶到一個合適的狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核準備好正確的環(huán)境。

  1. Boot Loader 所支持的 CPU 和嵌入式板

  每種不同的 CPU 體系結(jié)構(gòu)都有不同的 Boot Loader。有些 Boot Loader 也支持多種體系結(jié)構(gòu)的 CPU,比如 U-Boot 就同時支持 ARM 體系結(jié)構(gòu)和MIPS 體系結(jié)構(gòu)。除了依賴于CPU 的體系結(jié)構(gòu)外,BootLoader 實際上也依賴于具體的嵌入式板級設(shè)備的配置。這也就是說,對于兩塊不同的嵌入式板而言,即使它們是基于同一種 CPU 而構(gòu)建的,要想讓運行在一塊板子上的 Boot Loader 程序也能運行在另一塊板子上,通常也都需要修改Boot Loader 的源程序。

  2. Boot Loader 的安裝媒介(Installation Medium)

  系統(tǒng)加電或復(fù)位后,所有的 CPU 通常都從某個由 CPU 制造商預(yù)先安排的地址上取指令。比如,基于 ARM7TDMI core 的 CPU 在復(fù)位時通常都從地址 0x00000000 取它的第一條指令。而基于 CPU 構(gòu)建的嵌入式系統(tǒng)通常都有某種類型的固態(tài)存儲設(shè)備(比如:ROM、EEPROM 或 FLASH 等)被映射到這個預(yù)先安排的地址上。因此在系統(tǒng)加電后,CPU 將首先執(zhí)行 Boot Loader 程序。

  3. 用來控制 Boot Loader 的設(shè)備或機制

  主機和目標機之間一般通過串口建立連接,Boot Loader 軟件在執(zhí)行時通常會通過串口來進行 I/O,比如:輸出打印信息到串口,從串口讀取用戶控制字符等。

  4. Boot Loader 的啟動過程

  Boot Loader 的啟動過程是單階段(Single Stage)還是多階段(Multi-Stage)通常多階段的 Boot Loader 能提供更為復(fù)雜的功能,以及更好的可移植性。從固態(tài)存儲設(shè)備上啟動的 Boot Loader 大多都是 2 階段的啟動過程,也即啟動過程可以分為 stage 1 和stage 2 兩部分。而至于在 stage 1 和 stage 2 具體完成哪些任務(wù)將在下面討論。

  5. BootLoader 與主機之間進行文件傳輸所用的通信設(shè)備及協(xié)議

  最常見的情況就是,目標機上的 Boot Loader 通過串口與主機之間進行文件傳輸,傳輸協(xié)議通常是 xmodem/ymodem/zmodem 協(xié)議中的一種。但是,串口傳輸?shù)乃俣仁怯邢薜模虼送ㄟ^以太網(wǎng)連接并借助 TFTP 協(xié)議來下載文件是個更好的選擇。在討論了 BootLoader 的上述概念后,下面我們來具體看看 BootLoader 的應(yīng)該完成哪些任務(wù)。

  三。 Boot Loader 的主要任務(wù)與典型結(jié)構(gòu)框架

  在繼續(xù)本節(jié)的討論之前,首先我們做一個假定,那就是:假定內(nèi)核映像與根文件系統(tǒng)映像都被加載到 RAM 中運行。之所以提出這樣一個假設(shè)前提是因為,在嵌入式系統(tǒng)中內(nèi)核映像與根文件系統(tǒng)映像也可以直接在 ROM 或 Flash 這樣的固態(tài)存儲設(shè)備中直接運行。但這種做法無疑是以運行速度的犧牲為代價的。

  從操作系統(tǒng)的角度看,Boot Loader 的總目標就是正確地調(diào)用內(nèi)核來執(zhí)行。另外,由于 Boot Loader 的實現(xiàn)依賴于 CPU 的體系結(jié)構(gòu),因此大多數(shù) Boot Loader 都分為 stage1 和 stage2 兩大部分。依賴于 CPU 體系結(jié)構(gòu)的代碼,比如設(shè)備初始化代碼等,通常都放在 stage1 中,而且通常都用匯編語言來實現(xiàn),以達到短小精悍的目的。

  而 stage2 則通常用C語言來實現(xiàn),這樣可以實現(xiàn)給復(fù)雜的功能,而且代碼會具有更好的可讀性和可移植性。

  Boot Loader 的 stage1 通常包括以下步驟(以執(zhí)行的先后順序):

  硬件設(shè)備初始化。

  為加載 Boot Loader 的 stage2 準備 RAM 空間。

  拷貝 Boot Loader 的 stage2 到 RAM 空間中。

  設(shè)置好堆棧。

  跳轉(zhuǎn)到 stage2 的 C 入口點。

  Boot Loader 的 stage2 通常包括以下步驟(以執(zhí)行的先后順序):

  初始化本階段要使用到的硬件設(shè)備。

  檢測系統(tǒng)內(nèi)存映射(memory map)。

  將 kernel 映像和根文件系統(tǒng)映像從 flash 上讀到 RAM 空間中。

  為內(nèi)核設(shè)置啟動參數(shù)。

  調(diào)用內(nèi)核。

  3.1 Boot Loader 的 stage1

  3.1.1基本的硬件初始化

  這是 Boot Loader 一開始就執(zhí)行的操作,其目的是為 stage2 的執(zhí)行以及隨后的 kernel 的執(zhí)行準備好一些基本的硬件環(huán)境。它通常包括以下步驟(以執(zhí)行的先后順序):

  屏蔽所有的中斷。為中斷提供服務(wù)通常是 OS 設(shè)備驅(qū)動程序的責(zé)任,因此在 BootLoader 的執(zhí)行全過程中可以不必響應(yīng)任何中斷。中斷屏蔽可以通過寫CPU 的中斷屏蔽寄存器或狀態(tài)寄存器(比如ARM 的 CPSR 寄存器)來完成。

  設(shè)置 CPU 的速度和時鐘頻率。

  RAM 初始化。包括正確地設(shè)置系統(tǒng)的內(nèi)存控制器的功能寄存器以及各內(nèi)存庫控制寄存器等。

  初始化 LED。典型地,通過 GPIO 來驅(qū)動 LED,其目的是表明系統(tǒng)的狀態(tài)是 OK 還是 Error。如果板子上沒有 LED,那么也可以通過初始化 UART 向串口打印 Boot Loader 的 Logo 字符信息來完成這一點。

  關(guān)閉 CPU 內(nèi)部指令/數(shù)據(jù) cache。

  3.1.2 為加載 stage2 準備 RAM 空間

  為了獲得更快的執(zhí)行速度,通常把 stage2 加載到 RAM 空間中來執(zhí)行,因此必須為加載Boot Loader 的 stage2 準備好一段可用的 RAM 空間范圍。由于 stage2 通常是 C 語言執(zhí)行代碼,因此在考慮空間大小時,除了 stage2 可執(zhí)行映象的大小外,還必須把堆棧空間也考慮進來。此外,空間大小最好是 memory page 大小(通常是 4KB)的倍數(shù)。一般而言,1M的 RAM 空間已經(jīng)足夠了。具體的地址范圍可以任意安排,比如 blob 就將它的 stage2 可執(zhí)行映像安排到從系統(tǒng) RAM 起始地址 0xc0200000 開始的1M空間內(nèi)執(zhí)行。

  但是,將 stage2 安排到整個 RAM 空間的最頂 1MB(也即(RamEnd-1MB) - RamEnd)是一種值得推薦的方法。

  為了后面的敘述方便,這里把所安排的 RAM 空間范圍的大小記為:stage2_size(字節(jié)) ,把起始地址和終止地址分別記為:stage2_start 和 stage2_end(這兩個地址均以 4 字節(jié)邊界對齊)。因此: stage2_end=stage2_start+stage2_size

  另外,還必須確保所安排的地址范圍的的確確是可讀寫的 RAM 空間,因此,必須對你所安排的地址范圍進行測試。

  具體的測試方法可以采用類似于 blob 的方法,也即:以 memory page 為被測試單位,測試每個 memory page 開始的兩個字是否是可讀寫的。為了后面敘述的方便,我們記這個檢測算法為:test_mempage,其具體步驟如下:

  先保存 memory page 一開始兩個字的內(nèi)容。

  向這兩個字中寫入任意的數(shù)字。比如:向第一個字寫入 0x55,第 2 個字寫入 0xaa。

  然后,立即將這兩個字的內(nèi)容讀回。顯然,我們讀到的內(nèi)容應(yīng)該分別是 0x55 和 0xaa。如果不是,則說明這個 memory page 所占據(jù)的地址范圍不是一段有效的 RAM 空間。

  再向這兩個字中寫入任意的數(shù)字。比如:向第一個字寫入 0xaa,第 2 個字中寫入0x55。

  然后,立即將這兩個字的內(nèi)容立即讀回。顯然,我們讀到的內(nèi)容應(yīng)該分別是 0xaa和 0x55。如果不是,則說明這個 memory page 所占據(jù)的地址范圍不是一段有效的 RAM空間。

  恢復(fù)這兩個字的原始內(nèi)容。測試完畢。

  為了得到一段干凈的 RAM 空間范圍,我們也可以將所安排的 RAM 空間范圍進行清零操作。

  3.1.3 拷貝 stage2 到 RAM 中

  拷貝時要確定兩點:

  (1) stage2 的可執(zhí)行映象在固態(tài)存儲設(shè)備的存放起始地址和終止地址;

  (2) RAM 空間的起始地址。

  3.1.4 設(shè)置堆棧指針 sp

  堆棧指針的設(shè)置是為了執(zhí)行 C 語言代碼作好準備。通常我們可以把 sp 的值設(shè)置為(stage2_end-4),也即在 3.1.2 節(jié)所安排的那個 1MB 的 RAM 空間的最頂端(堆棧向下生長)。

  此外,在設(shè)置堆棧指針 sp 之前,也可以關(guān)閉 led 燈,以提示用戶我們準備跳轉(zhuǎn)到 stage2。

  經(jīng)過上述這些執(zhí)行步驟后,系統(tǒng)的物理內(nèi)存布局應(yīng)該如下圖2所示。

  3.1.5 跳轉(zhuǎn)到 stage2 的 C 入口點

  在上述一切都就緒后,就可以跳轉(zhuǎn)到 Boot Loader 的 stage2 去執(zhí)行了。

  比如,在 ARM 系統(tǒng)中,這可以通過修改 PC 寄存器為合適的地址來實現(xiàn)。

  3.2 Boot Loader 的stage2

  正如前面所說,stage2 的代碼通常用 C 語言來實現(xiàn),以便于實現(xiàn)更復(fù)雜的功能和取得更好的代碼可讀性和可移植性。

  但是與普通 C 語言應(yīng)用程序不同的是,在編譯和鏈接boot loader 這樣的程序時,我們不能使用 glibc 庫中的任何支持函數(shù)。其原因是顯而易見的。這就給我們帶來一個問題,那就是從那里跳轉(zhuǎn)進 main() 函數(shù)呢?直接把 main() 函數(shù)的起始地址作為整個 stage2 執(zhí)行映像的入口點或許是最直接的想法。但是這樣做有兩個缺點:

  1)無法通過main() 函數(shù)傳遞函數(shù)參數(shù);

  2)無法處理 main() 函數(shù)返回的情況。

  一種更為巧妙的方法是利用 trampoline(彈簧床)的概念。也即,用匯編語言寫一段trampoline 小程序,并將這段 trampoline 小程序來作為 stage2 可執(zhí)行映象的執(zhí)行入口點。然后我們可以在 trampoline 匯編小程序中用 CPU 跳轉(zhuǎn)指令跳入 main() 函數(shù)中去執(zhí)行;而當 main() 函數(shù)返回時,CPU 執(zhí)行路徑顯然再次回到我們的 trampoline 程序。簡而言之,這種方法的思想就是:用這段 trampoline 小程序來作為main() 函數(shù)的外部包裹(external wrapper)。

  下面給出一個簡單的 trampoline 程序示例(來自blob):

  .text

  .globl _trampoline

  _trampoline:

  bl main

  /* if main ever returns we just call it again */

  b _trampoline

  可以看出,當 main() 函數(shù)返回后,我們又用一條跳轉(zhuǎn)指令重新執(zhí)行 trampoline 程序,當然也就重新執(zhí)行 main() 函數(shù),這也就是 trampoline(彈簧床)一詞的意思所在。

  3.2.1初始化本階段要使用到的硬件設(shè)備

  這通常包括:

  (1)初始化至少一個串口,以便和終端用戶進行 I/O 輸出信息;

  (2)初始化計時器等。

  在初始化這些設(shè)備之前,也可以重新把 LED 燈點亮,以表明我們已經(jīng)進入 main() 函數(shù)執(zhí)行。

  設(shè)備初始化完成后,可以輸出一些打印信息,程序名字字符串、版本號等。

  3.2.2 檢測系統(tǒng)的內(nèi)存映射(memory map)

  所謂內(nèi)存映射就是指在整個 4GB 物理地址空間中有哪些地址范圍被分配用來尋址系統(tǒng)的RAM 單元。

  比如,在 SA-1100 CPU 中,從 0xC000,0000 開始的512M地址空間被用作系統(tǒng)的 RAM 地址空間,而在 Samsung S3C44B0X CPU 中,從 0x0c00,0000 到 0x1000,0000 之間的64M地址空間被用作系統(tǒng)的 RAM 地址空間。雖然 CPU 通常預(yù)留出一大段足夠的地址空間給系統(tǒng) RAM,但是在搭建具體的嵌入式系統(tǒng)時卻不一定會實現(xiàn) CPU 預(yù)留的全部 RAM 地址空間。也就是說,具體的嵌入式系統(tǒng)往往只把 CPU 預(yù)留的全部 RAM 地址空間中的一部分映射到 RAM 單元上,而讓剩下的那部分預(yù)留 RAM 地址空間處于未使用狀態(tài)。

  由于上述這個事實,因此 Boot Loader 的 stage2 必須在它想干點什么 (比如,將存儲在 flash 上的內(nèi)核映像讀到 RAM 空間中) 之前檢測整個系統(tǒng)的內(nèi)存映射情況,也即它必須知道CPU 預(yù)留的全部 RAM 地址空間中的哪些被真正映射到 RAM 地址單元,哪些是處于 “unused” 狀態(tài)的。

  (1) 內(nèi)存映射的描述

  可以用如下數(shù)據(jù)結(jié)構(gòu)來描述 RAM 地址空間中的一段連續(xù)(continuous)的地址范圍:

  typedef struct memory_area_struct {

  u32 start; /* the base address of the memory region */

  u32 size; /* the byte number of the memory region */

  int used;

  } memory_area_t;

  這段 RAM 地址空間中的連續(xù)地址范圍可以處于兩種狀態(tài)之一:

  (1)used=1,則說明這段連續(xù)的地址范圍已被實現(xiàn),也即真正地被映射到 RAM 單元上。

  (2)used=0,則說明這段連續(xù)的地址范圍并未被系統(tǒng)所實現(xiàn),而是處于未使用狀態(tài)。

  基于上述 memory_area_t 數(shù)據(jù)結(jié)構(gòu),整個 CPU 預(yù)留的 RAM 地址空間可以用一個 memory_area_t 類型的數(shù)組來表示,如下所示:

  memory_area_t memory_map[NUM_MEM_AREAS] = {

  [0 。.. (NUM_MEM_AREAS - 1)] = {

  .start = 0,

  .size = 0,

  .used = 0

  },

  };

  (2) 內(nèi)存映射的檢測

  下面我們給出一個可用來檢測整個 RAM 地址空間內(nèi)存映射情況的簡單而有效的算法:

  /* 數(shù)組初始化 */

  for(i = 0; i < NUM_MEM_AREAS; i++)

  memory_map[i].used = 0;

  /* first write a 0 to all memory locations */

  for(addr = MEM_START; addr < MEM_END; addr += PAGE_SIZE)

  * (u32 *)addr = 0;

  for(i = 0, addr = MEM_START; addr < MEM_END; addr += PAGE_SIZE) {

  /*

  * 檢測從基地址 MEM_START+i*PAGE_SIZE 開始,大小為

  * PAGE_SIZE 的地址空間是否是有效的RAM地址空間。

  */

  調(diào)用3.1.2節(jié)中的算法test_mempage();

  if ( current memory page isnot a valid ram page) {

  /* no RAM here */

  if(memory_map[i].used )

  i++;

  continue;

  }

  /*

  * 當前頁已經(jīng)是一個被映射到 RAM 的有效地址范圍

  * 但是還要看看當前頁是否只是 4GB 地址空間中某個地址頁的別名?

  */

  if(* (u32 *)addr != 0) { /* alias? */

  /* 這個內(nèi)存頁是 4GB 地址空間中某個地址頁的別名 */

  if ( memory_map[i].used )

  i++;

  continue;

  }

  /*

  * 當前頁已經(jīng)是一個被映射到 RAM 的有效地址范圍

  * 而且它也不是4GB 地址空間中某個地址頁的別名。

  */

  if (memory_map[i].used == 0) {

  memory_map[i].start = addr;

  memory_map[i].size = PAGE_SIZE;

  memory_map[i].used = 1;

  } else {

  memory_map[i].size += PAGE_SIZE;

  }

  } /* end of for (…) */

  在用上述算法檢測完系統(tǒng)的內(nèi)存映射情況后,Boot Loader 也可以將內(nèi)存映射的詳細信息打印到串口。

  3.2.3 加載內(nèi)核映像和根文件系統(tǒng)映像

  (1)規(guī)劃內(nèi)存占用的布局

  這里包括兩個方面:

  內(nèi)核映像所占用的內(nèi)存范圍;

  根文件系統(tǒng)所占用的內(nèi)存范圍。

  在規(guī)劃內(nèi)存占用的布局時,主要考慮基地址和映像的大小兩個方面。

  對于內(nèi)核映像,一般將其拷貝到從(MEM_START+0x8000) 這個基地址開始的大約1MB大小的內(nèi)存范圍內(nèi)(嵌入式 Linux 的內(nèi)核一般都不超過 1MB)。為什么要把從 MEM_START 到MEM_START+0x8000 這段 32KB 大小的內(nèi)存空出來呢?這是因為 Linux 內(nèi)核要在這段內(nèi)存中放置一些全局數(shù)據(jù)結(jié)構(gòu),如:啟動參數(shù)和內(nèi)核頁表等信息。

  而對于根文件系統(tǒng)映像,則一般將其拷貝到 MEM_START+0x0010,0000 開始的地方。如果用 Ramdisk 作為根文件系統(tǒng)映像,則其解壓后的大小一般是1MB。

  (2)從 Flash 上拷貝

  由于像 ARM 這樣的嵌入式 CPU 通常都是在統(tǒng)一的內(nèi)存地址空間中尋址 Flash 等固態(tài)存儲設(shè)備的,因此從 Flash 上讀取數(shù)據(jù)與從 RAM 單元中讀取數(shù)據(jù)并沒有什么不同。用一個簡單的循環(huán)就可以完成從 Flash 設(shè)備上拷貝映像的工作:

  while(count) {

  *dest++ = *src++; /* they are all aligned with word boundary */

  count -= 4; /* byte number */

  };

  3.2.4 設(shè)置內(nèi)核的啟動參數(shù)

  應(yīng)該說,在將內(nèi)核映像和根文件系統(tǒng)映像拷貝到 RAM 空間中后,就可以準備啟動 Linux 內(nèi)核了。

  但是在調(diào)用內(nèi)核之前,應(yīng)該作一步準備工作,即:設(shè)置 Linux 內(nèi)核的啟動參數(shù)。

  Linux 2.4.x 以后的內(nèi)核都期望以標記列表(tagged list)的形式來傳遞啟動參數(shù)。啟動參數(shù)標記列表以標記 ATAG_CORE 開始,以標記 ATAG_NONE 結(jié)束。每個標記由標識被傳遞參數(shù)的 tag_header 結(jié)構(gòu)以及隨后的參數(shù)值數(shù)據(jù)結(jié)構(gòu)來組成。

  數(shù)據(jù)結(jié)構(gòu) tag 和 tag_ header 定義在 Linux 內(nèi)核源碼的include/asm/setup.h 頭文件中:

  /* The list ends with an ATAG_NONE node. */

  #define ATAG_NONE 0x00000000

  struct tag_header {

  u32 size; /* 注意,這里size是字數(shù)為單位的 */

  u32 tag;

  };

  ……

  struct tag {

  struct tag_header hdr;

  union {

  struct tag_core core;

  struct tag_mem32 mem;

  struct tag_videotext videotext;

  struct tag_ramdisk ramdisk;

  struct tag_initrd initrd;

  struct tag_serialnr serialnr;

  struct tag_revision revision;

  struct tag_videolfb videolfb;

  struct tag_cmdline cmdline;

  /*

  * Acorn specific

  */

  struct tag_acorn acorn;

  /*

  * DC21285 specific

  */

  struct tag_memclk memclk;

  } u;

  };

  在嵌入式 Linux 系統(tǒng)中,通常需要由 Boot Loader 設(shè)置的常見啟動參數(shù)有:ATAG_CORE、ATAG_MEM、ATAG_CMDLINE、ATAG_RAMDISK、ATAG_INITRD等。

  比如,設(shè)置 ATAG_CORE 的代碼如下:

  params = (struct tag *)BOOT_PARAMS;

  params->hdr.tag = ATAG_CORE;

  params->hdr.size = tag_size(tag_core);

  params->u.core.flags = 0;

  params->u.core.pagesize = 0;

  params->u.core.rootdev = 0;

  params = tag_next(params);

  其中,BOOT_PARAMS 表示內(nèi)核啟動參數(shù)在內(nèi)存中的起始基地址,指針 params 是一個 struct tag 類型的指針。

  宏 tag_next() 將以指向當前標記的指針為參數(shù),計算緊臨當前標記的下一個標記的起始地址。

  注意,內(nèi)核的根文件系統(tǒng)所在的設(shè)備ID就是在這里設(shè)置的。

  下面是設(shè)置內(nèi)存映射情況的示例代碼:

  for(i = 0; i < NUM_MEM_AREAS; i++) {

  if(memory_map[i].used) {

  params->hdr.tag = ATAG_MEM;

  params->hdr.size = tag_size(tag_mem32);

  params->u.mem.start = memory_map[i].start;

  params->u.mem.size = memory_map[i].size;

  params = tag_next(params);

  }

  }

  可以看出,在 memory_map[]數(shù)組中,每一個有效的內(nèi)存段都對應(yīng)一個 ATAG_MEM 參數(shù)標記。

  Linux 內(nèi)核在啟動時可以以命令行參數(shù)的形式來接收信息,利用這一點我們可以向內(nèi)核提供那些內(nèi)核不

  能自己檢測的硬件參數(shù)信息,或者重載(override)內(nèi)核自己檢測到的信息。

  比如,我們用這樣一個命令行參數(shù)字符串“console=ttyS0,115200n8”來通知內(nèi)核以ttyS0 作為控制臺,且串口采用 “115200bps、無奇偶校驗、8位數(shù)據(jù)位”這樣的設(shè)置。下面是一段設(shè)置調(diào)用內(nèi)核命令行參數(shù)字符串的示例代碼:

  char *p;

  /* eat leading white space */

  for(p = commandline; *p == ‘ ’; p++)

  ;

  /* skip non-existent command lines so the kernel will still

  * use its default command line.

  */

  if(*p == ‘\0’)

  return;

  params->hdr.tag = ATAG_CMDLINE;

  params->hdr.size = (sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2;

  strcpy(params->u.cmdline.cmdline, p);

  params = tag_next(params);

  請注意在上述代碼中,設(shè)置 tag_header 的大小時,必須包括字符串的終止符‘\0’,此外還要將字節(jié)數(shù)向上圓整4個字節(jié),因為 tag_header 結(jié)構(gòu)中的size 成員表示的是字數(shù)。

  下面是設(shè)置 ATAG_INITRD 的示例代碼,它告訴內(nèi)核在 RAM 中的什么地方可以找到 initrd 映象(壓縮格式)以及它的大小:

  params->hdr.tag = ATAG_INITRD2;

  params->hdr.size = tag_size(tag_initrd);

  params->u.initrd.start = RAMDISK_RAM_BASE;

  params->u.initrd.size = INITRD_LEN;

  params = tag_next(params);

  下面是設(shè)置 ATAG_RAMDISK 的示例代碼,它告訴內(nèi)核解壓后的 Ramdisk 有多大(單位是KB):

  params->hdr.tag = ATAG_RAMDISK;

  params->hdr.size = tag_size(tag_ramdisk);

  params->u.ramdisk.start = 0;

  params->u.ramdisk.size = RAMDISK_SIZE; /* 請注意,單位是KB */

  params->u.ramdisk.flags = 1; /* automatically load ramdisk */

  params = tag_next(params);

  最后,設(shè)置 ATAG_NONE 標記,結(jié)束整個啟動參數(shù)列表:

  static void setup_end_tag(void)

  {

  params->hdr.tag = ATAG_NONE;

  params->hdr.size = 0;

  }

  3.2.5 調(diào)用內(nèi)核

  Boot Loader 調(diào)用 Linux 內(nèi)核的方法是直接跳轉(zhuǎn)到內(nèi)核的第一條指令處,

  也即直接跳轉(zhuǎn)到 MEM_START+0x8000 地址處。在跳轉(zhuǎn)時,下列條件要滿足:

  CPU 寄存器的設(shè)置:

  R0=0;

  R1=機器類型 ID;關(guān)于 Machine Type Number,可以參見 linux/arch/arm/tools/mach-types。

  R2=啟動參數(shù)標記列表在 RAM 中起始基地址;

  CPU 模式:

  必須禁止中斷(IRQs和FIQs);

  CPU 必須 SVC 模式;

  Cache 和 MMU 的設(shè)置:

  MMU 必須關(guān)閉;

  指令 Cache 可以打開也可以關(guān)閉;

  數(shù)據(jù) Cache 必須關(guān)閉;

  如果用 C 語言,可以像下列示例代碼這樣來調(diào)用內(nèi)核:

  void (*theKernel)(int zero, int arch, u32 params_addr) = (void (*)(int, int,u32))KERNEL_RAM_BASE;

  ……

  theKernel(0, ARCH_NUMBER, (u32) kernel_params_start);

  注意,theKernel()函數(shù)調(diào)用應(yīng)該永遠不返回的。如果這個調(diào)用返回,則說明出錯。

 

  四。 關(guān)于串口終端

 

  在 boot loader 程序的設(shè)計與實現(xiàn)中,沒有什么能夠比從串口終端正確地收到打印信息能更令人激動了。此外,向串口終端打印信息也是一個非常重要而又有效的調(diào)試手段。但是,我們經(jīng)常會碰到串口終端顯示亂碼或根本沒有顯示的問題。造成這個問題主要有兩種原因:

  boot loader 對串口的初始化設(shè)置不正確。

  運行在 host 端的終端仿真程序?qū)Υ诘脑O(shè)置不正確,這包括:波特率、奇偶校驗、數(shù)據(jù)位和停止位等方面的設(shè)置。

  此外,有時也會碰到這樣的問題,那就是:在 boot loader 的運行過程中我們可以正確地向串口終端輸出信息,但當 boot loader 啟動內(nèi)核后卻無法看到內(nèi)核的啟動輸出信息。對這一問題的原因可以從以下幾個方面來考慮:

  首先請確認你的內(nèi)核在編譯時配置了對串口終端的支持,并配置了正確的串口驅(qū)動程序。

  你的 boot loader 對串口的初始化設(shè)置可能會和內(nèi)核對串口的初始化設(shè)置不一致。此外,對于諸如 s3c44b0x 這樣的 CPU,CPU 時鐘頻率的設(shè)置也會影響串口,因此如果boot loader 和內(nèi)核對其 CPU 時鐘頻率的設(shè)置不一致,也會使串口終端無法正確顯示信息。

  最后,還要確認 boot loader 所用的內(nèi)核基地址必須和內(nèi)核映像在編譯時所用的運行基地址一致,尤其是對于 uClinux 而言。假設(shè)你的內(nèi)核映像在編譯時用的基地址是0xc0008000,但你的 boot loader 卻將它加載到 0xc0010000 處去執(zhí)行,那么內(nèi)核映像當然不能正確地執(zhí)行了。

 

  五。 結(jié)束語

  Boot Loader 的設(shè)計與實現(xiàn)是一個非常復(fù)雜的過程。如果不能從串口收到那激動人心的“uncompressing linux.。..。..。..。..。..。. done, booting the kernel……”內(nèi)核啟動信息,恐怕誰也不能說:“嗨,我的 boot loader 已經(jīng)成功地轉(zhuǎn)起來了!”。

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。
主站蜘蛛池模板: 色综合久久精品亚洲国产 | 里番本子纯肉侵犯肉全彩无码 | 日韩亚州| 成年美女黄网站色大免费视频 | 国精产品999国精产品蜜臀 | 女人下边被添全过视频的网址 | 日日噜噜夜夜狠狠久久波多野 | 狠狠躁天天躁综合网 | 亚洲三级网 | 国产伦孑沙发午休精品 | 午夜黄视频 | 午夜免费学生在线观看av | 国产成人无码精品久久久露脸 | 最新激情网站 | 粉嫩av亚洲一区二区图片 | 白嫩情侣偷拍呻吟刺激 | 国产91打白嫩光屁屁网站 | 白嫩嫩翘臀美女在线视频 | 好男人中文资源在线观看 | 黄色一级一片 | 视频在线观看网站免费 | 国产精品日韩欧美一区二区 | 国产毛片毛片精品天天看软件 | 极品av在线 | 日韩精品中文字幕在线观看 | 精品无码三级在线观看视频 | 少妇被粗大的猛进出69影院 | 粉嫩一区| 香蕉视频国产精品 | 国产视频成人 | 男女啪啪做爰高潮免费看 | 一级黄色大片在线观看 | 亚洲va成无码人在线观看天堂 | 偷拍中年夫妇激情嗷嗷叫 | aⅴ一区二区三区无卡无码 aⅴ在线免费观看 | 亚洲第一色 | 精品亚洲一区二区三区在线播放 | 免费观看av网址 | 亚洲免费观看 | 特黄三级男人添女人下面 | 日本精品视频一区 | 欧美黄色免费大片 | 国产亚洲精品久久久久久久久久久久 | 国产精品日韩精品欧美精品 | 亚洲色成人www永久网站 | 色婷五月天| 婷婷伊人综合亚洲综合网 | 国产精品久久久久久久久久久久午夜片 | 久久久久久久久91 | 国产伦精品一区二区三 | 欧美亚洲国产精品久久高清 | 欧美美女在线观看 | 粉嫩av一区二区在线播放免费 | 欧美黑人精品一区二区不卡 | 国内精品免费视频 | 麻豆md0077饥渴少妇 | 亚洲精品一区二区不卡 | 精品小视频在线观看 | 色呦色呦色精品 | www.午夜视频 | 美女露隐私免费网站 | 少妇视频一区 | 狠狠v欧美ⅴ日韩v亚洲v大胸 | 真人与拘做受免费视频 | 国产91在线亚洲 | 最近中文字幕在线中文高清版 | 大胸美女拍拍18在线观看 | 欧美日韩aaa | 亚洲日韩aⅴ在线视频 | 五月精品视频 | 懂色av中文一区二区三区 | 日本6一12娇小xxxⅹhd | 9l视频自拍九色9l视频 | 欧美日韩高清一区 | 国产精品久久国产 | 国产精品久久久久永久免费看 | 国色天香精品一卡2卡3卡 | 国产婷婷色综合av蜜臀av | 日韩午夜一区二区三区 | 初尝黑人嗷嗷叫中文字幕 | 四虎在线免费播放 | 欧美色综合色 | 日日爽视频 | 欧美三级在线 | 中文在线中文资源 | 国产亲子乱弄免费视频 | 四虎影城库| 精品人妻二区中文字幕 | 午夜剧场在线 | 伊人网在线视频观看 | 91精品国产91久久久久游泳池 | 中国一级特黄毛片大片 | 国产又黄又嫩又滑又白 | 亚洲区免费中文字幕影片|高清在线观看 | 国产精品三 | 国产麻豆一区 | 国产一级视频免费播放 | 夜夜噜噜噜 | 一级特黄aa大片欧美 | av看片| 粉嫩av久久一区二区三区小说 | 日日躁夜夜摸月月添添添的视频 | 中文在线a在线 | 18禁无遮挡羞羞污污污污网站 | 无码国产成人午夜电影在线观看 | 哈利波特3在线观看免费版英文版 | 午夜精品久久久久久久99樱桃 | 免费的毛片视频 | 欧美顶级metart裸体全部自慰 | 亚洲不卡在线视频 | 亚洲欧美综合精品另类天天更新 | 人妻av中文字幕久久 | 19禁国产精品福利视频 | gogo精品国模啪啪作爱 | 成人重囗味sm | 91在线看片| 欧美精品久久久久久久监狱 | 在线观看免费毛片 | 蜜桃香蕉视频 | 国产又粗又黄的视频 | 永久免费黄色片 | 大陆一级a毛片杨玉环 | 99热日本 | 国产精品乱码一区二区视频 | 精品无码一区二区三区的天堂 | 国产精品免费视频网站 | 久久99精品国产麻豆婷婷洗澡 | 中文字幕av伊人av无码av | 国产精品毛片一区二区在线看舒淇 | 欧美精品久久久久久久久 | 成人精品一区二区三区网站 | 久久夜色噜噜噜av一区二区 | 日韩欧美一区二区三区四区 | 三级精品视频 | 久久久久久久久久久91 | 久久人人爽人人爽人人片ⅴ | 国产精品视频网站 | 久草在线视频免费资源观看 | 99国产精品白浆在线观看免费 | 男人女人做爽爽18禁网站 | 夜夜动漫 | 日韩三级大片 | 天天干天天添 | av资源网站 | 亚洲日韩va无码中文字幕 | 国产全肉乱妇杂乱视频 | 91精品一线二线三线 | 日本高清一区二区三 | 亚洲欧美日韩精品久久亚洲区 | 国产乱码精品一区二区三 | 成年人午夜免费视频 | 亚洲成a人片在线 | 欧美人与性动交α欧美精品 | 农村老熟妇乱子伦视频 | av无码久久久久久不卡网站 | 天天做天天爱夜夜爽导航 | 欧美猛交ⅹxxx乱大交视频 | 瑜伽裤国产一区二区三区 | 久久午夜无码鲁丝片午夜精品 | 日本无遮挡吸乳呻吟免费视频网站 | 亚洲天天综合网 | 乱精品一区字幕二区 | 91桃色污| 99久久免费精品国产男女性高好 | 久久嗨 | 免费久久久久久 | 欧美久久久久久久高潮 | 亚洲a级在线观看 | 亚洲免费永久精品 | 国产一区二区久久久 | 一区二区久久久久 | 一区欧美| 人妻少妇精品视频二区 | 久久久久久久久久久久久久国产 | 午夜成人理论无码电影在线播放 | 国产不卡视频 | 久久综合久久网 | 91麻豆产精品久久久久久 | 女人爽得直叫免费视频 | 狠狠色狠狠色综合久久一 | 在线观看超碰 | 无码熟妇αⅴ人妻又粗又大 | 性一交一乱一色一视频 | 久久不见久久见免费影院国语 | 黄色一级在线 | 国产一线二线三线女 | 黄色小网站在线观看 | 国产精品视频全国免费观看 | 日韩激情久久 | 久久久久成人精品无码中文字幕 | 国产成人亚洲人欧洲 | 日本高清在线观看 | 国产精品中文字幕在线 | 婷婷开心深爱五月天播播 | 亚洲日韩精品一区二区三区无码 | 黑人一级女人全片 | 国产日韩不卡 | 国产精品嫩草影院桃色 | 伊人黄色片 | 成人欧美一区二区三区视频 | 国产精品高潮呻吟av久久4虎 | 欧美在线一二 | 精品视频一二三区 | 韩国午夜理伦三级2020苹果 | 中文字幕欧美人妻精品一区 | 熟妇人妻系列aⅴ无码专区友真希 | 亚洲人成网站色7799 | 一级片免费观看 | 99热久久是国产免费66 | 免费精品视频一区二区三区 | 爱吃波客今天最新视频 | 亚洲va中文字幕 | 东北妇女精品bbwbbw | 91精品国产综合久久香蕉最新版 | 黑人狂躁中国少妇and | 免费av网页 | 国产又粗又猛又爽又黄91网站 | 激情综合色综合久久综合 | 偷窥第一页 | 亚洲一区二区三区国产好的精华液 | 亚洲精品av天天看1080p | 亚洲无人区小视频 | 日本少妇18p | 国产九一视频在线观看 | 欧美第一页草草影院 | 欧美成a人片在线观看久 | 免费福利在线 | 88av网站 | 妞妞色www在线精品观看视频 | 日一日干一干 | 久热精品在线视频 | www国产亚洲精品久久网站 | 小罗莉极品一线天在线 | 在线观看av网页 | 日本高清裸体私密写真集 | 日本h在线 | 极品色av | 2020国产成人精品视频 | 在线观看亚洲精品视频 | 91综合中文字幕乱偷在线 | 国产第一精品 | 国产69精品久久久久久人妻精品 | 天天看夜夜爽 | 韩国av中文字幕 | 日韩中文一区二区 | 久久综合资源 | 人妻无码熟妇乱又伦精品视频 | 成人国产精品入口免费视频 | 麻豆国产一区二区三区四区 | 成人精品一区二区三区电影 | 中文字幕免费在线看线人动作大片 | 少妇影院7788 | 欧美人与野鲁交xxx视频 | 欧美极品少妇xxxxⅹ猛交 | 亚洲日韩乱码一区二区三区四区 | 不卡的av在线免费观看 | 欧美我不卡 | 好色先生视频污 | 精品国模一区二区三区 | 三级毛片在线看 | 久久久精品视频网站 | 免费一级淫片a人观看69 | 俺也去五月婷婷 | 丰满少妇被猛烈进入无码 | 在线视频亚洲色图 | 中文字幕第一页在线视频 | 国产美女高潮流白浆视频 | 在办公室被c到呻吟的动态图 | 青青草久久久 | 国产911视频| 天天摸天天干天天操 | 亚洲天堂网一区二区 | av丝袜在线观看 | 欧洲成人一区二区 | 亚洲伊人伊色伊影伊综合网 | 黄色一级播放 | 欧美日韩四区 | 色欲久久综合亚洲精品蜜桃 | 美女穴穴 | 欧美最新精品videossexohd | 人妻丰满熟av无码区hd | 久久久精品久久日韩一区综合 | 国产精品好爽好紧好大 | 国产亚洲美女精品久久久2020 | 日韩av在线播放不卡 | 亚洲人精品亚洲人成在线 | 极品美女一线天粉嫩 | 中国美女一级看片 | 婷婷影院在线 | 天堂а√中文最新版在线 | 色综合色综合 | 久久久久久久久久av | 国产99视频精品免视看芒果 | 色哟哟国产最新 | sm调教美女警花少妇 | 精品999久久久 | 一区二区三区蜜桃 | av色吧| 国产经典毛片 | 日韩欧美一中文字暮专区 | 国产成人精品视频ⅴa片软件竹菊 | 国产精品久久久久久久 | 久久 国产 尿 小便 嘘嘘 | 免费看成人哺乳视频 | 乱h伦h女h在线视频 乱lun合集小可的奶水 | 亚洲区自拍 | 夜夜嗨一区 | 97影音| 亚洲a视频在线 | 性高爱久久久久久久久 | 三级网站在线看 | 窝窝人体色www | 国产精品igao为爱做激情 | 性久久久久久久久 | 国产大片黄 | 亚洲网站在线 | 亚洲三级欧美 | 日韩精品中文字幕一区二区三区 | 情侣偷偷看的羞羞视频网站 | 精品中文字幕一区二区三区av | 动漫美女靠逼 | 久久亚洲天堂 | 中文字幕丰满伦子无码 | 国产91精品一区二区麻豆亚洲 | 精品亚洲成a人在线观看 | 开元在线观看视频国语 | 超碰女人 | 色美av | 日本一区二区三区视频免费看 | 国产精品久久免费观看spa | 久草视频国产 | 色乱码一区二区三区麻豆 | 香蕉视频官方网站 | 久久在线精品 | 精品乱人码一区二区二区 | www亚洲天堂 | 午夜精品久久久久久99热 | 五姑娘影院在线观看免费 | 国产成人无码专区 | 91人人草| 天干夜天干天天天爽2022 | 久久久久欧美精品999 | 午夜免费片 | 波多野av在线 | 亚洲视频日韩 | 精品无码一区二区三区爱欲 | 日韩人妻无码一区二区三区久久 | 掩来啦掩去啦最新官网 | 134vcc影院免费观看 | 中国大陆一级片 | 国产精品男人的天堂 | 亚洲 国产 另类 精品 专区 | 最新色视频 | 色网站在线观看 | 熟妇熟女乱妇乱女网站 | 玖玖热麻豆国产精品图片 | 性欧美视频一区二区三区 | 韩日午夜在线资源一区二区 | 黄色片视频免费观看 | 婷婷色在线 | 一本精品中文字幕在线 | 中国男女全黄大片 | 亚洲一级黄色大片 | 亚洲天天综合 | 成人黄色毛片 | 久草在线观看资源 | 俄罗斯毛片 | 在线观看色视频 | 国产精品人妻一码二码尿失禁 | 天天干天天日夜夜操 | 亚洲孕交 | 久久久久欧美精品999 | 激情亚洲色图 | 国产女女做受ⅹxx高潮 | 亚洲免费中文字幕 | 亚洲三级av | 成人无码影片精品久久久 | 少妇一区二区三区四区 | 亚洲日韩成人无码 | 四虎影视大全 | 欧美专区在线观看 | 成人av网址大全 | 国产精品另类激情久久久免费 | 亚洲中文字幕av无码专区 | 另类毛片| 亚洲一区在线免费 | 国产视频91在线 | 在线精品亚洲欧美日韩国产 | 最新av中文字幕 | xxxx野外性xxxx黑人 | 无码内射成人免费喷射 | 正在播放国产老头老太色公园 | 日韩在线观看一区 | 国产精品亚洲综合色区韩国 | 久操视频在线播放 | 久色精品 | 91成人在线免费视频 | 玖玖精品 | 五月天免费网站 | 无码少妇精品一区二区免费动态 | 脱岳裙子从后面挺进去在线观看 | 久草精品视频在线看网站免费 | 国产免费又粗又猛又爽 | 女人天堂网 | 亚洲国产成人无码av在线播放 | 黄视频在线免费 | 97国产在线 | 99热在线观看| 久久久久久久亚洲国产精品87 | 亚洲精品久久久久中文第一幕 | 亚洲色欲一区二区三区在线观看 | 日韩精品中文字幕一区 | 国产欧美一级二级三级在线视频 | 蜜桃视频在线观看免费视频网站www | 在线视频97 | 国产超碰人人模人人爽人人喊 | 天天拍夜夜添久久精品大 | 久久久久国产精品免费免费搜索 | 日韩精品高清在线 | 国产多p混交群体交乱 | 午夜激情视频 | 日韩一区二区在线观看视频 | 成人3d动漫一区二区三区 | 国产精品久久久久久久白丝制服 | 日韩有码在线播放 | 激情亚洲视频 | 欧美激情精品久久久久久免费 | 国产亚洲精品久久久闺蜜 | 成人亚洲精品久久久久软件 | 日本无遮挡真人祼交视频 | 日韩成人在线观看 | 在线观看少妇 | 亚洲视频免费播放 | 91麻豆精品国产午夜天堂 | 欧美一区视频在线 | 无码国内精品久久人妻 | 第一次处破女啪啪 | 国产高清在线视频 | 成人在线午夜视频 | 999精品嫩草久久久久久99 | 97在线播放 | 国产懂色av一区二区三区 | 91视频青青草 | 色七七亚洲 | 国产又黄又硬又粗 | 中国少妇无码专区 | 加勒比一区二区 | 国产婷婷色一区二区三区在线 | 欧美精品一区在线 | 亚洲高清在线观看 | 日韩av在线网| 欧美日韩人成综合在线播放 | 六月婷婷av | 国产绿帽口舌视频vk | 精品人妻久久久久久888 | 国产精品一级在线 | 黑人巨大精品欧美一区二区桃花岛 | 国产精品一区二区av | 人人草人人澡 | 免费高潮视频95在线观看网站 | 99热这里 | 久久精品一区二区国产 | 动漫av在线 | 精品无人区一区二区三区 | 这里只有精品国产 | 国产大片中文字幕在线观看 | 亚洲精品乱码久久久久久金桔影视 | 最近中文字幕免费mv视频7 | 丰满少妇高潮久久三区 | 日本一本在线 | 国产欧美日韩另类在线专区 | 中国女人精69xxxxxx视频 | 午夜无码免费福利视频网址 | 免费无码成人片 | 草久网| 国产又黄又猛又爽 | 欧美成人精品三级在线观看播放 | 999久久久国产精品 999久久久精品 | 国产在线一区二区三区 | 国产妞干网 | 国产卡一卡二在线 | 国产精品无码久久久久成人影院 | 老鸭窝视频在线观看 | 日本丰满护士bbw | 国产成人无码www免费视频播放 | 日本中文字幕第一页 | 色婷婷成人网 | 一个人看的视频在线观看www | 色欧美视频 | 丰满少妇奶水一区二区三区 | 国产精品视频第一区二区三区 | 人妻少妇中文字幕久久 | 亚洲精品免费在线视频 | 男女一级黄色 | 久久久福利 | 蜜臀av夜夜澡人人爽人人 | 国产精品一区二区含羞草 | 久久久久久亚洲精品不卡 | 国产免费福利视频 | 国产成人精品一区二区阿娇陈冠希 | 国产精品久久麻豆 | 交专区videossex另类 | 91丨九色丨首页 | 国产成年人网站 | 日本午夜寂寞影院 | 欧美日韩久久久久 | 99久久精品久久久久久动态片 | 天天搞天天干 | 偷看农村女人做爰毛片色 | 精品久久久久久无码专区不卡 | 2021av| 国产免费拔擦拔擦8x高清在线人 | 成人高清在线 | 涩涩爱在线 | 在线播放日韩精品 | 正在播放大战肉丝少妇 | 青青草成人在线观看 | 尹人av | 熟女人妻少妇精品视频 | 日韩精品一区二区在线播放 | 精品国产三级在线观看 | 午夜乱蜜桃久久久乱 | 欧美一区二区三区免费播放视频了 | 69精产国品一二三产区视频 | 丰满人妻熟妇乱又伦精品视 | 狠狠做五月深爱婷婷 | 精品视频在线观看一区二区 | 四虎亚洲精品 | 性插免费视频 | 五月婷婷狠狠干 | 久久免费看少妇高潮a | 中文字幕精品一区二区精品 | 色婷婷av一区二区三区之e本道 | 国产丝袜一区二区在线 | 色香蕉在线视频 | 亚洲欧美男人天堂 | 少妇一级淫片免费看 | 日本在线www| 第一页国产| 国产xxxxewxxxx性| 国产对白叫床清晰在线播放 | 一级做a爱片久久毛片 | 国产一毛片 | 一本之道色综合网站 | 日韩无套 | 国产成人艳妇aa视频在线 | 日产mv免费观看 | 风流老熟女一区二区三区 | 久草五月| 国产成人av大片大片在线播放 | 长篇h版少妇沉沦交换 | 夫妻性生活自拍 | 国产欧美一区二区精品久久久 | 免费看h网站 | 精品国产一区二区三区噜噜噜 | 欧色丰满女同hd | 最新欧美大片 | 免费裸体无遮挡黄网站免费看 | 免费日韩欧美 | 草草在线观看视频 | 日韩欧美四区 | 国产美女免费看 | 国产精品成人免费一区久久羞羞 | 国产区在线观看 | 亚洲国产成人精品综合av | 一二三区在线视频 | 三级视频网站 | 黑人巨大猛交丰满少妇 | 久久影音先锋 | 欧美久久久久久久 | 亚洲精品成人无限看 | 日韩一区二区三区免费视频 | 美女流白浆视频 | 又色又爽又黄gif动态图 | 性开放xxxhd视频| 无码国产精品一区二区色情男同 | 国产精品-色哟哟 | 五月av在线| 干干人人| 小视频免费在线观看 | 久久久久国色av免费看 | 波多野结衣视频免费看 | 日韩精品成人av | 免费av在线播放 | 一本久久道| 国内精品国产成人国产三级 | 国产精品毛片va一区二区三区 | 草的我好爽视频 | 狠狠躁天天躁无码中文字幕 | 亚洲女同在线 | 日韩高清影视在线观看 | 乱人伦中文视频在线观看 | 一本久在线 | 亚洲国产精品国自产拍av秋霞 | 亚洲国产精品久久久久爰色欲 | 久久综合国产伦精品免费 | 国产精品岛国久久久久久久久红粉 | 精品人妻中文无码av在线 | 欧美在线一区二区 | 欧美尿交 magnet | 尤物videos另类xxxx | 黑人上司好猛我好爽中文字幕 | 丰满的继牳3中文字幕系列 丰满的少妇xxxxx人伦理 | 亚洲国产精品视频在线观看 | 久久精品成人av | 黄网站色 | 婷婷六月综合网 | 狠狠鲁视频| 欧美一区二区网站 | 一道本在线观看视频 | 一区二区三区国产 | 国产精品最新 | 黄色a级网站 | 欧美日韩一区免费 | 加比勒色综合久久 |