亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

嵌入式Linux學習:u-boot源碼分析(6)--AM335X系列的2014.10版

2019-11-14 10:18:00
字體:
來源:轉載
供稿:網友

題外話

    之前的5篇博文簡單介紹了AM335X啟動過程中關于SPL階段的代碼,可以看到SPL實際上沒干什么活,它主要是初始化了SDRAM,并根據實際情況將MMC或者其他Flash中的uboot鏡像一股腦的加載到SDRAM中的低位位置。然后將cpu的指針指向了SDRAM低位,在SDRAM低位中執行uboot代碼!    這是為了最大化的合理分配SDRAM的內存空間,讓uboot可以更好的運行,也給后期linux內核騰出更多的空間,所以必須要將uboot放置到SDRAM的高位再執行。之前的博客中介紹了,很多變量以及代碼段都是位置相關的,也就是運行地址在連接的時候就已經確定了,只有將相應的代碼放置到特定的位置才可以保證沒有錯誤的運行。所以講低位的uboot賦值到SDRAM高位以后,必須要做重定位!    所以后續的代碼任務就是:    1. 準備一個臨時的gd和sp    2. 將SDRAM的高位人為的劃分出一部分空間作為uboot區(類似的還有gd區,bd區,malloc區)    3. 然后將原本保存到低位的uboot復制到高位,也就是上述的uboot區    4. 重定位    5.跳到高位的uboot中運行(已經重定位,所以運行沒有問題)

匯編部分

    我們再次回到了start.S的reset處,還記得SPL的入口嗎,實際上也是在這里,只是SPL和uboot分別是根據不同的條件做的編譯,所以其函數定義也會有所不同,我們繼續看這么一段匯編的代碼:
reset:	bl	save_boot_params /*lowlevel_init.S (arch/arm/cpu/armv7/omap-common)*/	/*	 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,	 * except if in HYP mode already	 */	mrs	r0, cpsr	and	r1, r0, #0x1f		@ mask mode bits	teq	r1, #0x1a		@ test for HYP mode	bicne	r0, r0, #0x1f		@ clear all mode bits	orrne	r0, r0, #0x13		@ set SVC mode	orr	r0, r0, #0xc0		@ disable FIQ and IRQ	msr	cpsr,r0/* * Setup vector: * (OMAP4 spl TEXT_BASE is not 32 byte aligned. * Continue to use ROM code vector only in OMAP4 spl) */#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))	/* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */	mrc	p15, 0, r0, c1, c0, 0	@ Read CP15 SCTRL Register	bic	r0, #CR_V		@ V = 0	mcr	p15, 0, r0, c1, c0, 0	@ Write CP15 SCTRL Register	/* Set vector address in CP15 VBAR register */	ldr	r0, =_start	mcr	p15, 0, r0, c12, c0, 0	@Set VBAR#endif	/* the mask ROM code should have PLL and others stable */#ifndef CONFIG_SKip_LOWLEVEL_INIT/*this branch will only work in SPL*/	bl	cpu_init_cp15 /*wlg: find out in this file, we do not explain in detial*/	bl	cpu_init_crit /*wlg: find out in this file, please jump*/#endif	bl	_main	/*wlg: jump to arch/arm/lib/crt0.s*/    沒毛病,上面的代碼和這個博客(1)中是一樣的,至少看起來是一樣的,它主要執行了以下功能:    1. bl save_boot_params 這是第一個不同于SPL階段的代碼,之前save_boot_params保存了r0寄存器中的數據到SRAM中,在uboot中,它實際上只是:
ENTRY(save_boot_params)	bx	lr			@ back to my callerENDPROC(save_boot_params)	.weak	save_boot_params        可以看到,此時的r0早就已經被SPL用了很多次,上次已經不再保存啟動信息了,而且這時候啟動信息也已經不再重要了,因為我們已經正在執行uboot了,所以上面的代碼只是做了簡單的返回。    2.  請注意,這個時候CONFIG_SPL_BUILD不再被定義,所以后面的很多條件編譯請自覺忽略。關閉了中斷,設置了SVC后    3. 這個時候我們會定義CONFIG_SKIP_LOWLEVEL_INIT,所以其后面的cpu_init_cp15等代碼實際上不會被執行,而是直接來到了_main, arch/arm/lib/crt0.s    接下來繼續看_main代碼,實際上也是和SPL一樣的,只是部分條件編譯不一樣,如下:
ENTRY(_main)/* * Set up initial C runtime environment and call board_init_f(0). */#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)	ldr	sp, =(CONFIG_SPL_STACK)/* wlg: in spl, it seems be 0x40310000-sizeof(global_data)*/#else	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)/* wlg: in uboot, it will be ?*/#endif	bic	sp, sp, #7	/* 8-byte alignment for ABI compliance		|		      	SPL			|			uboot		|*/	mov	r2, sp	/* wlg: we record the end of address of the initial 	|sp is useful, r9 (gdata) will |sp is useful,  a new temp 	|*/	sub	sp, sp, #GD_SIZE	/* allocate one GD above SP 				|be redefined in board_init_f	|GD(pointed by r9) will be  	|*/				bic	sp, sp, #7	/* 8-byte alignment for ABI compliance		|so next text is only to clear	| set above on sp,   gdata 	|*/	mov	r9, sp		/* GD is above SP 							|a invalid memory			|be discarded 			|*/	mov	r1, sp	/* wlg: we record the start address of the initial*/	mov	r0, #0 	/*wlg : the num of initialition*/clr_gd:	cmp	r1, r2			/* while not at end of GD */	strlo	r0, [r1]		/* clear 32-bit GD Word */ /*wlg: ro >> [r1]*/	addlo	r1, r1, #4		/* move to next */	blo	clr_gd#if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_BUILD)	sub	sp, sp, #CONFIG_SYS_MALLOC_F_LEN	str	sp, [r9, #GD_MALLOC_BASE]#endif	/* mov r0, #0 not needed due to above code */	bl	board_init_f 	/*wlg: SPL: board_init_f - Function in spl.c (arch/arm/lib) , and it will not return, it will jump to uboot's start's*/						/*wlg: Uboot: board_init_f - Function in Board.c (arch/arm/lib) at line 263 (199 lines), it will return*/    上述代碼主要完成了:    1. 設置一個臨時的sp,為后面的C語言函數調用做準備    2. 在這個臨時的sp上分配出一部分空間專門用來保存全局變量,并把這部分空間清0,并將r9指向這個全局變量!請注意,這里的全局變量已經不同于SPL階段的gdata(全局變量),這里的全局變量是一個臨時的用來保存關鍵數據的。所以請記住,在uboot的前期所用到的全局變量(會用gd指針表示)實際上指的就是建立在SRAM上的這部分空間,而且已經初始化為0,不再繼承SPL階段的全局變量(SPL階段的全局變量雖然也是保存在SRAM中,但是是預先定義好的.data中)    3. 定義一個malloc空間,并將malloc空間的地址賦值給最新的臨時全局變量(因為r9所指就是全局變量的開頭,其加上一個偏移量后就是gd->malloc_base)    4. 萬事俱備(有了臨時sp和全局變量,為什么說是臨時的呢?因為這兩個玩意都還建立在SRAM上,而我們cpu目前試運行在SDRAM上的,我們最終希望sp和全局變量都是指向SDRAM的?。?,那么接下來就可以轉跳到從語言函數board_init_f,他的定義位置和SPL不同,在Board.c (arch/arm/lib)

C語言部分

    這部分代碼很長,我們分幾次將其貼上
void board_init_f(ulong bootflag){	bd_t *bd;	init_fnc_t **init_fnc_ptr;	gd_t *id;	ulong addr, addr_sp;#ifdef CONFIG_PRAM	ulong reg;#endif	void *new_fdt = NULL;	size_t fdt_size = 0;	memset((void *)gd, 0, sizeof(gd_t));//DECLARE_GLOBAL_DATA_PTR make gd >> r9,	//wlg:  all we now used gd is a point which saved in r9, so it is point to SRAM	gd->mon_len = (ulong)&__bss_end - (ulong)_start;//wlg:  it will be the sum size of uboot, it should be made at ld?#ifdef CONFIG_OF_EMBED	/* Get a pointer to the FDT */	gd->fdt_blob = __dtb_dt_begin;#elif defined CONFIG_OF_SEPARATE	/* FDT is at end of image */	gd->fdt_blob = &_end;#endif	/* Allow the early environment to override the fdt address */	gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,						(uintptr_t)gd->fdt_blob);	//initial function sequence as defined before, containing serial_init()	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {		if ((*init_fnc_ptr)() != 0) {			hang ();		}	}#ifdef CONFIG_OF_CONTROL	/* For now, put this check after the console is ready */	if (fdtdec_prepare_fdt()) {		panic("** CONFIG_OF_CONTROL defined but no FDT - please see "			"doc/README.fdt-control");	}#endif	debug("monitor len: %08lX/n", gd->mon_len);	/*	 * Ram is setup, size stored in gd !!	 */	debug("ramsize: %08lX/n", gd->ram_size);    這部分代碼的主要工作是對對全局變量進行賦值,也就是上文gd所指向的建立在SRAM上的臨時全局變量;然后利用函數指針進行各種初始化,展示如下:
init_fnc_t *init_sequence[] = {	arch_cpu_init,		/* basic arch cpu dependent setup */	mark_bootstage,#ifdef CONFIG_OF_CONTROL	fdtdec_check_fdt,#endif#if defined(CONFIG_BOARD_EARLY_INIT_F)	board_early_init_f,#endif	timer_init,		/* initialize timer */#ifdef CONFIG_BOARD_POSTCLK_INIT	board_postclk_init,#endif#ifdef CONFIG_FSL_ESDHC	get_clocks,#endif	env_init,		/* initialize environment */	init_baudrate,		/* initialze baudrate settings */	serial_init,		/* serial communications setup */ 	//wlg: at very first of SPL, we have no serial, so we get the default serial as cerrent	console_init_f,		/* stage 1 init of console */			//wlg: while in boot, 	display_banner,		/* say that we are here */ //wlg: now we have the first information printed out: U-Boot 2014.10...	print_cpuinfo,		/* display cpu info (and speed) */#if defined(CONFIG_DISPLAY_BOARDINFO)	checkboard,		/* display board info */#endif#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)	init_func_i2c,#endif	dram_init,		/* configure available RAM banks */// wlg: make initialing to gd->ram-size	NULL,};    將上面的函數指針數組中的元素所指向的函數全部執行一遍,每一個函數都比較簡單,其作用在注釋中都有所記錄。初始化過程也會對上述全局變量gd中元素做修改,初始化過程也大量用到了環境變量,這些默認的環境變量在編譯時就已經確定,下次專門開一篇來介紹環境變量!
	addr = CONFIG_SYS_SDRAM_BASE + get_effective_memsize();	//wlg: now, we could divide the menory to parts as follow#ifdef CONFIG_LOGBUFFER#ifndef CONFIG_ALT_LB_ADDR	/* reserve kernel log buffer */	addr -= (LOGBUFF_RESERVE);	debug("Reserving %dk for kernel logbuffer at %08lx/n", LOGBUFF_LEN,		addr);#endif#endif#ifdef CONFIG_PRAM	/*	 * reserve protected RAM	 */	reg = getenv_ulong("pram", 10, CONFIG_PRAM);	addr -= (reg << 10);		/* size is in kB */	debug("Reserving %ldk for protected RAM at %08lx/n", reg, addr);#endif /* CONFIG_PRAM */#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))	/* reserve TLB table */	gd->arch.tlb_size = PGTABLE_SIZE;//wlg: tlb will be 64KB	addr -= gd->arch.tlb_size;	/* round down to next 64 kB limit */	addr &= ~(0x10000 - 1);	gd->arch.tlb_addr = addr;//wlg: record the addr in global_data	debug("TLB table from %08lx to %08lx/n", addr, addr + gd->arch.tlb_size);#endif	/* round down to next 4 kB limit */	addr &= ~(4096 - 1);	debug("Top of RAM usable for U-Boot at: %08lx/n", addr);#ifdef CONFIG_LCD#ifdef CONFIG_FB_ADDR	gd->fb_base = CONFIG_FB_ADDR;#else	/* reserve memory for LCD display (always full pages) */	addr = lcd_setmem(addr);	gd->fb_base = addr;#endif /* CONFIG_FB_ADDR */#endif /* CONFIG_LCD */	/*	 * reserve memory for U-Boot code, data & bss	 * round down to next 4 kB limit	 */	addr -= gd->mon_len;	addr &= ~(4096 - 1);	debug("Reserving %ldk for U-Boot at: %08lx/n", gd->mon_len >> 10, addr); 
////////////////////////////the different between SPL and uboot ///////////////////////////////#ifndef CONFIG_SPL_BUILD//////////////wlg: in this branch, we put the global_data and board_data into SDRAM	/*	 * reserve memory for malloc() arena	 */	addr_sp = addr - TOTAL_MALLOC_LEN;	debug("Reserving %dk for malloc() at: %08lx/n",			TOTAL_MALLOC_LEN >> 10, addr_sp);	/*	 * (permanently) allocate a Board Info struct	 * and a permanent copy of the "global" data	 */	addr_sp -= sizeof (bd_t);	bd = (bd_t *) addr_sp;	gd->bd = bd;	debug("Reserving %zu Bytes for Board Info at: %08lx/n",			sizeof (bd_t), addr_sp);#ifdef CONFIG_MACH_TYPE	gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */#endif	addr_sp -= sizeof (gd_t);	id = (gd_t *) addr_sp;	debug("Reserving %zu Bytes for Global Data at: %08lx/n",			sizeof (gd_t), addr_sp);#if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL)	/*	 * If the device tree is sitting immediate above our image then we	 * must relocate it. If it is embedded in the data section, then it	 * will be relocated with other data.	 */	if (gd->fdt_blob) {		fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);		addr_sp -= fdt_size;		new_fdt = (void *)addr_sp;		debug("Reserving %zu Bytes for FDT at: %08lx/n",		      fdt_size, addr_sp);	}#endif#ifndef CONFIG_ARM64	/* setup stackpointer for exeptions */	gd->irq_sp = addr_sp;#ifdef CONFIG_USE_IRQ	addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);	debug("Reserving %zu Bytes for IRQ stack at: %08lx/n",		CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);#endif	/* leave 3 words for abort-stack    */	addr_sp -= 12;	/* 8-byte alignment for ABI compliance */	addr_sp &= ~0x07;#else	/* CONFIG_ARM64 */	/* 16-byte alignment for ABI compliance */	addr_sp &= ~0x0f;#endif	/* CONFIG_ARM64 */ 上面的代碼完成了SDRAM高位地址的劃分,從SDRAM頂上往下依次是:    a. TLB,放置TLB。請注意這里只是劃分出這么個空間作為TLB的區域,里面并沒有數據!    b.FB LCD,放置frame buffer 緩沖(一般沒有)    c. Uboot  .text .data .bss,放置完整的uboot代碼段和bss數據。請注意這里只是劃分出這么個空間作為uboot的區域,里面并沒有數據!    d. malloc 放置molloc空間。請注意這里只是劃分出這么個空間作為malloc的區域,里面并沒有數據!    e. bd 放置board data 結構體。請注意這里只是劃分出這么個空間作為bd的區域,里面并沒有數據!    f. gd 放置 global data結構體,這個gd結構體才是真正在后期uboot要用的全局變量。請注意這里只是劃分出這么個空間作為gd的區域,里面并沒有數據!    g. IRQ stack。請注意這里只是劃分出這么個空間作為IRQ的區域,里面并沒有數據!    h. sp,這個sp才是后期uboot要用的堆棧。請注意這里只是劃分出這么個空間作為sp的區域,里面并沒有數據!    請注意,上述代碼只是簡單的劃分了SDRAM的內存區域,比如說uboot區域,實際上當前正在執行的就是uboot程序,只是當前代碼目前保存在SDRAM的低位,上述的uboot區是在SDRAM的高端,后期我們會將低位的uboot復制到高位的uboot區,再執行重定位,然后代碼就可以安全的在高位執行了!    在完后看
	gd->relocaddr = addr;	//wlg: the uboot start here	gd->start_addr_sp = addr_sp; //wlg: the stack is here	gd->reloc_off = addr - (ulong)&_start; //wlg:  record the offset, we will relocation.	debug("relocation Offset is: %08lx/n", gd->reloc_off);	if (new_fdt) {		memcpy(new_fdt, gd->fdt_blob, fdt_size);		gd->fdt_blob = new_fdt;	}	memcpy(id, (void *)gd, sizeof(gd_t));	//wlg: copy the temp global_data the the static global_data in SDRAM    劃分完SDRAM后,需要將關鍵參數保存到gd中,此時的gd仍是SRAM中的臨時全局變量,最后那一句,就將在SRAM中的全局變量,復制到了處在SDRAM中的全局變量中。也就是說現在的全局變量有兩個備份,一個在SRAM中,另一個在SDRAM中!-------------------------------返回到_main------------------------
	ldr	sp, [r9, #GD_START_ADDR_SP]	/* sp = gd->start_addr_sp */	/*wlg: because r9 point to SRAM and keep gd*/	bic	sp, sp, #7	/* 8-byte alignment for ABI compliance */			/*wlg: and also we have a copy in SDRAM*/	ldr	r9, [r9, #GD_BD]		/* r9 = gd->bd */ 				/*wlg: we should change r9 to point to SDRAM*/	sub	r9, r9, #GD_SIZE		/* new GD is below bd */			/*wlg:  <<<<<change r9<<<<<<<<<<<<<*/																/*wlg:  also, we change sp to point to SDRAM*/	adr	lr, here	ldr	r0, [r9, #GD_RELOC_OFF]		/* r0 = gd->reloc_off */		/*wlg:  now r9 is point to SDRAM*/	add	lr, lr, r0												/*wlg:  lr will be the here function which run in SDRAM*/	ldr	r0, [r9, #GD_RELOCADDR]		/* r0 = gd->relocaddr */		/*wlg: so when we return, the program will run on SDRAM*/	b	relocate_code			/*the function is locate in relocate.S (arch/arm/lib)*/
here:    這段代碼在注視中解釋的很清晰了,其作用就是:    a. 更新r9,讓其指向SDRAM中的全局變量!因為以前面已經完成了SRAM到SDRAM的全局變量復制        i.第一句中的r9還是指向SRAM,其作用就是將SRAM中的全局變量中的start_addr_sp賦值給sp,這樣就完成了sp指向SDRAM中正確位置的工作!后做對齊        ii.第三句的r9還是指向SRAM,其作用就是將SRAM中的全局變量中的bd賦值給r9        iii.將此時的r9減去GD_SIZE的(即全局變量的size)后,再賦值給r9,此時的r9已經正確的指向了SDRAM中的全局變量(而且已經將SRAM中的相應數據復制進去)    b. 將此時的here標號的地址賦值給lr,將r0賦值為重定位的偏移地址r0 = gd->reloc_off,將lr加上這個r0,這樣就相當于完成了here(lr)的重定位!    c.將r0賦值為gd->relocaddr,這個地址就是在SDRAM中重新分配的uboot的起始地址(這個uboot區域目前還沒有數據)    d. 跳到relocate_code進行重定位!注意這里不是用bl,所以實際上沒有記錄返回地址。前面我們已經將here的重定位地址賦給了lr,所以relocate_code返回的話,就會返回到重定位后的SDRAM中區執行,也就是在上述SDRAM中的uboot段中區執行。    注意:uboot原本也是運行在SDRAM中,但是從SDRAM的地址分配來看,我們無法提前預知uboot的最佳運行位置。所以uboot的前期都是在SDRAM的低位運行的,而且前期的代碼都是位置無關的,所以執行起來沒有問題。直到重定位完成以后,才將uboot搬移到SDRAM中的uboot區(人為劃分的,實際運行的最佳位置),這個時候開始,uboot才開始復雜的功能!所以接下來的重定位非常的關鍵。    可看之前的博客-講解重定位的那篇
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人免费高清完整版在线观看| 亚洲成年人在线| 国产精品亚洲第一区| 国产日韩精品在线观看| 久久久久久999| 隔壁老王国产在线精品| 国产成人精品在线播放| 久久久女女女女999久久| 日韩在线高清视频| 久久久久久国产精品三级玉女聊斋| 亚洲石原莉奈一区二区在线观看| 国产剧情久久久久久| 国产做受69高潮| 一区二区三区高清国产| 欧美一级淫片播放口| 成人在线精品视频| 亚洲国产精品va在线看黑人| 高清欧美性猛交xxxx黑人猛交| 国产精品高清在线| 国产欧美一区二区三区视频| 色综合五月天导航| 精品福利视频导航| 亚洲日本成人女熟在线观看| 国产精品777| 国产69精品久久久| 狠狠色香婷婷久久亚洲精品| 免费av一区二区| 国产成人97精品免费看片| 欧美日韩亚洲一区二| 欧美一区二区三区图| 日韩精品在线观看一区| 国产精品久久久久不卡| 北条麻妃一区二区三区中文字幕| 欧美电影在线播放| 欧美性理论片在线观看片免费| 国产日韩在线视频| 成人激情av在线| 一区二区三欧美| 亚洲国内精品视频| 欧美日产国产成人免费图片| 中文字幕av一区二区| 亚洲成年人影院在线| 亚洲免费视频在线观看| 91精品视频大全| 国产精品夫妻激情| 日韩美女av在线免费观看| 夜夜嗨av色综合久久久综合网| 久久视频在线播放| 国产日韩欧美夫妻视频在线观看| …久久精品99久久香蕉国产| 亚洲欧美另类自拍| 欧美久久精品午夜青青大伊人| 成人有码视频在线播放| 亚洲欧美在线磁力| 免费av一区二区| 最新国产精品亚洲| 91国产美女在线观看| 一区二区亚洲欧洲国产日韩| 日韩黄在线观看| 日本精品视频在线| 国产福利视频一区| 久久成人精品一区二区三区| 久久躁日日躁aaaaxxxx| 欧美性做爰毛片| 色综合久久精品亚洲国产| 欧美日韩国产综合新一区| 日韩av手机在线看| 亚洲国产精品va在线观看黑人| 精品小视频在线| 97久久国产精品| 91九色单男在线观看| 亚洲视频国产视频| 久久99热精品这里久久精品| 中文字幕日韩在线观看| 成人在线播放av| 国产69精品久久久| 欧美日韩一区二区在线播放| 91探花福利精品国产自产在线| 久久久久久有精品国产| 日本中文字幕不卡免费| 日韩中文字幕av| 欧美成人激情视频免费观看| 色偷偷亚洲男人天堂| 欧洲美女免费图片一区| 久久久久久久久综合| 国产精品aaa| 超薄丝袜一区二区| 国产精品亚洲一区二区三区| 亚洲xxxx视频| 国产精品入口日韩视频大尺度| 午夜精品久久久久久久久久久久久| 51久久精品夜色国产麻豆| 68精品久久久久久欧美| 精品人伦一区二区三区蜜桃网站| 国产精品丝袜视频| 国产精品com| 久久亚洲精品一区| 中文字幕亚洲一区在线观看| 性欧美办公室18xxxxhd| 久久这里只有精品视频首页| 亚洲第一av网站| 一区二区三区无码高清视频| 91最新国产视频| 欧美日韩电影在线观看| 久久亚洲国产精品成人av秋霞| 久久久久久国产精品三级玉女聊斋| 中文字幕视频在线免费欧美日韩综合在线看| 日韩av片永久免费网站| 亚洲深夜福利网站| 日韩av网站导航| 亚洲成人精品视频在线观看| 亚洲尤物视频网| 性色av一区二区三区免费| 亚洲福利视频免费观看| 韩国精品久久久999| 国产69精品久久久久99| 人体精品一二三区| 国产成人在线亚洲欧美| 欧美大尺度激情区在线播放| 国产精国产精品| 亚洲欧美综合另类中字| 日韩福利视频在线观看| 久久久精品视频在线观看| 久久久亚洲国产| 这里只有精品丝袜| 亚洲偷欧美偷国内偷| 欧美丝袜第一区| 亚洲а∨天堂久久精品喷水| 在线观看欧美www| 亚洲人成在线观看网站高清| 成人国产精品色哟哟| 国产精品亚洲精品| 91国在线精品国内播放| 亚洲午夜久久久影院| 欧美精品一区二区免费| 亚洲视频一区二区三区| 欧美肥老妇视频| 欧美日韩精品中文字幕| 日本午夜人人精品| 国产欧美精品久久久| 欧美精品一区二区免费| 91国产中文字幕| 97在线日本国产| 久久精品成人欧美大片古装| 色综合天天狠天天透天天伊人| 日本久久亚洲电影| 欧美性猛交丰臀xxxxx网站| 国色天香2019中文字幕在线观看| 亚洲xxx大片| 色先锋久久影院av| 欧美韩国理论所午夜片917电影| 欧美成人免费小视频| 啪一啪鲁一鲁2019在线视频| 欧美成年人在线观看| 日韩精品在线免费播放| 日韩在线观看免费全| 精品女厕一区二区三区| 欧美最猛性xxxxx亚洲精品| 97碰在线观看| 国产精品日韩电影| 国产精品一久久香蕉国产线看观看| 亚洲视频777| 日韩视频在线免费| 日韩av影片在线观看|