Linux 移植流水賬

來源:互聯網
上載者:User

Linux 移植流水賬

首先,要看晶片的核Linux是否支援,如果不支援,那麼工作量極其大,放棄吧。
如果cpu核linux支援的話,移植linux,主要是根據SOC所整合的外圍模組,將驅動完成。
下面以一款ARM926ejs的晶片為例,在linux 26.22.5上的移植 。
假設晶片叫 MYCHIP
第一步 環境的建立 :
1 在config檔案中添加你的晶片支援
  a)  mkdir arch/arm/mach_mychip, 添加Kconfig和Makefile檔案
修改arch/arm/Kconfig :
menu "System Type"
choice
    prompt "ARM system type"
    default ARCH_MYCHIP
config ARCH_MYCHIP
    bool "my chip "
    select ARM_AMBA
    help
      This enables support for mychip
-------
source "arch/arm/mach-mychip/Kconfig"
這樣 make menuconfig ARCH=arm 就出現了你的晶片 。
b) 在arch/arm/mm/Kconfig 中
# ARM926T
config CPU_ARM926T
depends on ---| |   ARCH_MYCHIP
deafult if ............. | |   ARCH_MYCHIP
這樣就申明你的晶片屬於 arm 926
c) 在 include/asm-arm/下建立一個目錄 mach-mychip
然後修改arch/arm/Makefile 加上 :
machine-$(CONFIG_ARCH_MYCHIP)       := mychip
這樣當選擇上你的晶片時,編譯的時候 會將 include/asm-arm/.arch 連結到
include/asm-arm/arch-mychip
2 加上cpu的配置
a) 在arch/arm/tools中,mach_types加上晶片ID
b) 配置cpu的起始物理地址 和時鐘頻率
編譯
將提示asm/arch/memory.h,asm/arch/timex.h這兩個檔案沒有。
建立include/asm-arm/arch-mychip/memory.h
#define PHYS_OFFSET     UL(0x60000000)
這個是根據晶片SDRAM的 地址空間,比如我現在所用的晶片它的SDRAM地址空間為:6000 0000 – 67FF FFFF 128M
#define __virt_to_bus(x)        __virt_to_phys(x)
#define __bus_to_virt(x)        __phys_to_virt(x)
這兩個是:Virtual view <-> DMA view memory address translations
建立include/asm-arm/arch-mychip/timex.h
#define CLOCK_TICK_RATE         (50000000 / 16)
linux用宏 CLOCK_TICK_RATE來表示輸入時鐘脈衝的頻率.
在linux中,1秒中時鐘中斷的次數 以HZ表示,對於arm #define HZ 100 也就是10ms來一次時鐘中斷,
Linux用宏LATCH來定義要寫到計數器中的值,隔多少個刻度產生一次時鐘中斷。顯然LATCH應該由下列公式計算:
LATCH=(1秒之內的刻度個數)÷(1秒之內的時鐘中斷次數)=(CLOCK_TICK_RATE)÷(HZ)
c) 配置vmalloc 虛擬位址分配
編譯
提示 缺少 asm/arch/vmalloc.h:
建立include/asm-arm/arch-mychip/vmalloc.h
#define VMALLOC_END             (PAGE_OFFSET + 0x18000000)
PAGE_OFFSET 啟始的虛擬位址的分配, linux分為核心空間和使用者空間,核心空間為3G-4G,所以PAGE_OFFSET定義為 0xC0000000
VMALLOC_END:
(轉http://www.lslnet.com/linux/f/docs1/i34/big5260475.htm)
vmalloc(見mm/vmalloc.c檔案)的目的是供內核分配在虛擬空間必須是連續的大塊內存(物理地址不要求連續),其所佔用的地址範圍是特定於平台的常數VMALLOC_START和VMALLOC_END定義的
(轉http://idcnews.net/html/edu/20080101/281406.html)
Linux用vm_struct結構來表示vmalloc使用的線性地址.vmalloc所使用的線性地址區間為: VMALLOC_START VMALLOC_END.借用>中的一副插圖,如下示:

d) 配置中斷,IO ,DMA
編譯 inux移植流水帳
將提示缺少 :asm/arch/irqs.h,asm/arch/dma.h,asm/arch/io.h這三個檔案
建立irqs.h,在這個檔案中 主要是定義NR_IRQS ,以及定義中斷的宏,比如定義
#define I2C_INT                     39
標記I2C中斷為39號 ,以後在程式裡 好用
request_irq( I2C_INT......)
建立 include/asm-arm/arch-dw/io.h,這個檔案主要定義IO地址到記憶體位址的轉換
建立 include/asm-arm/arch-dw/dma.h,這個檔案主要DMA方面的一些定義
e) 查詢中斷號的宏實現
這個和特定的CPU有關,就是通過查詢中斷狀態器,得知現在是那個中斷
編譯
提示缺少include/asm-arm/arch-mychip/entry-macro.S
這個檔案主要是low level IRQ helper 宏 get_irqnr_and_base,該宏擷取irq中斷號,儲存到r0寄存器中,作為參數傳遞給asm_do_IRQ
加上下面兩個宏:
.macro  get_irqnr_preamble, base, tmp
                .endm
       .macro  arch_ret_to_user, tmp1, tmp2
                .endm
f)hardware.h
編譯
提示缺少include/asm-arm/arch-mychip/hardware.h
g) 設定系統idle ,reset函數
編譯 提示缺少asm/arch/system.h:
這個檔案主要實現 arch_idle 和arch_reset 2個函數
arch_reset 根據晶片,按次序設定一些寄存器 ,讓系統重啟
3
  a)上面的步驟做好後,將驅動全部去掉,編譯,將提示 arch/arm/arch-mychip/built_in.o找不到,
在arch/arm/arch-mychip中隨便添加一個mychip.c檔案 ,修改makefile
obj-y                   := mychip.c
b) 編譯工具檢查
編譯 出現
   no machine record defined
原來在arch/arm/kernel/vmlinux.lds末尾 :
ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
這表明我們的編譯工具太老了,一看,編譯工具是arm-2006q3, 2006第3季度的 ,確實太老了。
升級到arm-2008q3,編譯還是出現這個問題。
我們編譯出錯,因為沒有arch.info.init這個區,那麼這個區在哪裡定義的呢? 在linux/include/asm-arm/mach/arch.h 中發現MACHINE_START宏定義:
#define MACHINE_START(_type,_name)                      /
static const struct machine_desc __mach_desc_##_type    /
__used                                                 /
__attribute__((__section__(".arch.info.init"))) = {    /
        .nr             = MACH_TYPE_##_type,            /
        .name           = _name,
#define MACHINE_END                             /
};
因此 在mychip.c中 加上 __enable_mmu
   MACHINE_START(XXXX, "ARM-DW")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
MACHINE_END
XXXX根據arch/arm/tools/mach-types
第二步 :啟動kernel
1  將uImage 啟動後,
在列印
   Start Kernel ....
後出現
undefined instruction
   Start Kernel .... 是在uboot /lib_arm/armlinux.c 的    do_bootm_linux函數中 ,開始啟動kernel時列印的
那後面呢???
2 在uboot中對 SDRAM和串口已經初始化了,但在Linux中也有串口的驅動,串口驅動初始化後,就可以用printk列印東西了,在之前,怎麼列印呢?需要實現putc函數 .
在include/asm-arm/arch-mychip中,添加uncompress.h,實現putc,flush函數 。
3 原來是缺少 Makefile.boot檔案
在arch/arm/boot/Makefile中,會include $(srctree)/$(MACHINE)/Makefile.boot
建立arch/arm/mach-mychip/Makefile.boot
該檔案主要定義
zreladdr-y  0x60008000 核心解壓縮後的執行地址 (0x60000000 SDRAM基地址+0x00008000)
params_phys-y 0x60000100 核心參數物理地址  (0x60000000 SDRAM基地址 +0x00000100)
initrd_phys-y  initrd物理地址
4 還是不行 ,用一個可以啟動的uImage 進行對比
好的:
## Booting image at 62000000 ...
   Image Name:   Kernel Image
   Created:      2009-03-18   6:23:44 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1452480 Bytes =  1.4 MB
   Load Address: 60008000
   Entry Point:  60008000
出現undefined instrution 的 uImage:
## Booting image at 62000000 ...
   Image Name:   Kernel Image
   Created:      2009-03-20   9:42:06 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2217548 Bytes =  2.1 MB
   Load Address: 30008000
   Entry Point:  30008000
兩者的load Address ,entry point不一樣,
這是在uboot 的 common/cmd_bootm.c 的 do_bootm函數中 ,調用
print_image_hdr ((image_header_t *)addr);
uImage的 頭為 一個image_hear_t結構 。
Load Address 應該在Makefile.boot中定義為zreladdr-y  60008000啊 怎麼變成 30008000了呢 ?而且大小也不對阿,怎麼2.1 M
後來終於發現,我用的是./uImage 而不是arch/arm/boot/uImage ,而./uImage為非壓縮核心,在./Makefile中,用的是 :
        $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S vmlinux linux.bin
        mkimage -A $(ARCH) -O linux -T kernel -C none -a 30008000 -e 30008000 -n "Kernel Image Giant" -d linux.bin uImage
,需要修改成:
$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S vmlinux linux.bin
mkimage -A $(ARCH) -O linux -T kernel -C none -a 60008000 -e60008000 -n "Kernel Image Giant" -d linux.bin uImage,
換成arch/arm/boot/uImag後
## Booting image at 62000000 ...
   Image Name:   Linux-2.6.22.5
   Created:      2009-03-20  10:13:20 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)  //mkimage 沒有再壓縮zImage
   Data Size:    1108164 Bytes =  1.1 MB
   Load Address: 60008000
   Entry Point:  60008000
OK
Start Kernel ....
怎麼後面沒有了呢 ??

怎麼自動就產生了uncompressed uImage呢?

一開始怎麼也不理解,應該是compressed uImage啊? 預設的應該是產生compressed uImage .
原來,在include/asm-arm/mach-mychip/uncompress.h中 ,用的是串口1,而我們接的是串口2,修改這個檔案,讓串口2輸出。
在Start Kernel .... 後出現
Uncompressing Linux....................................................................... done, booting the kernel.
說明kernel是壓縮的,並正確解壓了。
如果用非壓縮核心 ,則改為./uImage ,下載後:
## Booting image at 62000000 ...
   Image Name:   Kernel Image Giant
   Created:      2009-03-23   5:42:39 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2217548 Bytes =  2.1 MB
   Load Address: 60008000
   Entry Point:  60008000
OK
5 解壓完核心後,或者下載非壓縮核心後,
由於在start_kernel一開始就調用printk, 但其實並不是立即就輸出,而是放在一個buffer中,__log_buf

直到register_console調用後,register_console註冊完後調用release_console_sem(),release_console_sem-->call_console_drivers列印緩衝區裡的東西.

也就是說在調用register_console之前的printk,並不列印,而是放在buffer中,在註冊console時,把之前列印的立即發送出去.

   register_console之後的printk可以立即列印資料.

那麼在哪裡會調用register_console呢?

   uart_add_one_port ->register_console
因此在uart驅動沒完成之前,在misc.c中,有一個函數putstr,他直接調用putc ,然後調用flush .

要麼在start_kernel中,也這樣來試試,看看問題出在哪裡 ?
在start_kernel的一開始,用putc('c');flush();  沒輸出,那說明在調用start_kernel之前就出錯了.
在/init/main.c中 加入:
#include
asmlinkage void __init lawrence_debug(void)
{
  putc('a');
  putc('b');
  putc('/n');
   flush();
}
用這個函數來看到底在哪裡出問題了(asmlinkage一定要,否則在彙編中調用不了)。
然後在./arch/arm/kernel/head.S中,加入 bl lawrence_debug , 看程式跑到哪裡。
發現,原來是 在 __lookup_machine_type後死機了,進入了__error_a,也就是沒找到machine_type ,
在head-Common.S中,__lookup_machine_type函數的輸入參數是r1 (machine architecture number),而這個參數是 uboot中傳入的。

為了更好的看到底問題出在哪裡,可以開啟CONFIG_DEBUG_LL宏來看.
http://blog.csdn.net/aaronychen/archive/2008/08/27/2838341.aspx
好像__lookup_machine_type的r1不對,修改為:
  __lookup_machine_type:
       mov r1 ,#0x32
       orr r1 ,r1,#0x400
就可以找到machine  了,怎麼uboot就沒傳過來呢??
6  開啟CONFIG_DEBUG_LL宏,提示缺少debug-macro.S,
這個檔案主要是為了 printascii等函數用 ,它定義了4個宏
addruart : 得到UART的地址,看晶片UARAT1或者2 的地址,這裡有個問題,MMU如果沒開啟,那地址好辦,
                      MMU開啟了呢?則需要提供虛擬位址,IO的虛擬位址通過下面的方法:
在 MACHINE_START中定義了.map_io = mychip_map_io
                       mychip_map_io -> iotable_init (map_desc ...) ,map_desc結構中定義了IO地址和虛擬位址的對應 關係 ,
在/init/main.c的start_kernel -->startup_arch( arch/arm/kernel/setup.c) -->paging_init(在arch/arm/mm/init.c 中)-->devicemaps_init -->map_io
senduart  :發送內容
waituart   : 等待
busyuart   : 判斷是否busy , busy 的話迴圈
測試這個檔案很簡單,在head.S中 bl __error_a 看看有沒有列印出來
7  發現 :
   ldr        r13, __switch_data                @ address to jump to after
                                                @ mmu has been enabled     
         adr        lr, __enable_mmu                @ return (PIC) address    
------走到此處
         add        pc, r10, #PROCINFO_INITFUNC
r10 為 procinfo的基地址, 因此  add pc ,r10 ...  將執行 __cpu_flush 也就是 __arm926_setup(arch/arm/mm/proc_arm926.S) , 該函數最後  mov pc ,lr 將調用  __enable_mmu
__enable_mmu --> __turn_mmu_on -> mov pc ,r13 將 調用  __switch_data
而在 __map_switched 下面調用 bl __error_a 沒反應
在__turn_mmu_on函數中 ,
__turn_mmu_on:
        mov     r0, r0
此處用   bl __error_a 有列印
        mcr     p15, 0, r0, c1, c0, 0           @ write control reg
        mrc     p15, 0, r3, c0, c0, 0           @ read id reg
        mov     r3, r3
        mov     r3, r3
此處用        bl __error_a 沒有列印
        mov     pc, r13
這說明 ,在 MMU起效後 , addruart將用虛擬位址 ,而此時IO的虛擬位址是多少呢 ??
這個要根據
      .phys_io       =        0x05C00000,              // UART2 phy addr
      .io_pg_offst    = ((0xf0000000) >> 18) & 0xfffc,  //UART2 virt addr
將5c00000 映射到 0xf0000000
修改 debug-macro.S
  .macro  addruart,rx
                mrc     p15, 0, /rx, c1, c0
                tst     /rx, #1                 @ MMU enabled?
                moveq   /rx, #0x05C00000        @ physical
                movne   /rx, #0xf0000000        @ virtual
                .endm
這樣就可以列印出來了 。
8 在main.c start_kernel前定義 :
#define UART2_TX_FIFO_LEVELV (*(volatile unsigned char *)0xf0000020)
#define UART2_TX_DATAV       (*(volatile unsigned char *)0xf0000028)
static inline void putcv(int c)
{
        //wait until there is space in TX FIFO
        while(UART2_TX_FIFO_LEVELV == 0x80)
                barrier();
        UART2_TX_DATAV = c;
}
static inline void flushv(void)
{
        while(UART2_TX_FIFO_LEVELV)
                barrier();
}
asmlinkage void __init lawrence_debug(void)
{
  putcv('a');
  putcv('b');
  putcv('/n');
   flushv();
}
asmlinkage void __init start_kernel(void)
{
        char * command_line;
        extern struct kernel_param __start___param[], __stop___param[];
        lawrence_debug();
     .....
發現列印出來了 。
至此  start_kernel終於運行了。

第三步:系統初始化
1 系統啟動流程大致為:
start_kernel :
  setup_arch ....
  init_IRQ -->init_arch_irq
  ...
  timer_init   -->system_timer ...
  ... rest_init -->將調用init call
在 MACHINE_START裡面有 :
        .map_io         = mychip_map_io,
        .init_irq       = mychip_init_irq,
        .timer          = &mychip_timer,
        .init_machine   = mychip_init, 
在/init/main.c的start_kernel -->setup_arch( arch/arm/kernel/setup.c) -->paging_init(在arch/arm/mm/init.c 中)-->devicemaps_init -->map_io,     mychip_map_io -> iotable_init (map_desc ...) ,map_desc結構中定義了IO地址和虛擬位址的對應 關係 ,
我們用一個宏 IO_ADDRESS (include/asm/arch/hardware.h)
:#define IO_ADDRESS(x)              (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
將 x  ---> 0xfx ( x 在0x00000000 ~ 0x0f000000 )
    x  ---> 0xf(x+1~f) ( x 在0x10000000 ~ 0xf0000000 )
我們晶片的IO地址都在0x00000000 ~ 0x0f00000000 之間 ,所以物理地址變成虛擬位址只是加上了0xf0000000,變成高位地址 。
最終 映射關係為 :
其他的IO  --> 0xF0000000 (包括 NAND Flash controller ,TDM ....)
   SRAM         --->0xD0000000
  SDRAM       ---> 0xC0000000
  NOR Flash沒有映射 ,只能通過 mtdblock0 ,mtdblock1來訪問 ?????
修改
     .phys_io       =        0x05C00000,              // UART2 phy addr
      .io_pg_offst    = ((IO_ADDRESS(0x5C00000)) >> 18) & 0xfffc,  //UART2 virt addr
將5c00000 映射到 0xf5C00000
修改 debug-macro.S
    .macro  addruart,rx
                mrc     p15, 0, /rx, c1, c0
                tst     /rx, #1                 @ MMU enabled?
                moveq   /rx, #0x00000000        @ physical
                movne   /rx, #0xf0000000        @ virtual
                orr     /rx, /rx, #0x05C00000   @ UART2 offset
                .endm
這樣就對應起來 。 可以在任何時候都用lawrence_debug看系統跑到哪裡了。
在main.c start_kernel前定義 :
#define UART2_TX_FIFO_LEVELV (*(volatile unsigned char *)0xf5C00020)
#define UART2_TX_DATAV       (*(volatile unsigned char *)0xf5C00028)
setup_arch的末尾將:
      init_arch_irq = mdesc->init_irq;
        system_timer = mdesc->timer;
        init_machine = mdesc->init_machine;
在arch/arm/kernel/setup.c中
customize_machine  --> init_machine
arch_initcall(customize_machine);
對於 init_irq ,主要是結構體 static struct irq_chip , 並將set_irq_handler(i, handle_level_irq);
並且 注意 在低版本的SA_INTERRUPT 替換成 IRQF_DISABLED
                                       SA_TIMER        替換成 IRQF_TIMER
                                      set_irq_chipdata 替換成 set_irq_chip_data
而 timer 主要是提供系統時鐘(tick),這樣,每到一個tick,發生任務切換。

第四步: 添加console驅動
console驅動就是輸出printk的資訊 。 這是第一步,這樣在程式中可以用printk來列印,看執行到哪裡。
對於 驅動的添加,利用platform driver model , 現在 arch init 中,用amba_device_register加入device ,
然後在module_init中 用 amba_driver_register註冊驅動,在註冊驅動的過程中,會根據amba_driver中的idtable (包括id和mask)來和device中的periphid 比較 ,看能否match ,能的話就調用probe函數 。
對於 嵌入式裝置,console是用輸出到uart ,所以只要在uart的驅動中定義struct console mychip_console
然後在struct uart_driver mychip_reg中的.cons = &mychip_console ,這樣在probe函數中加上
uart_add_one_port(&mychip_reg,....) 就會把console註冊上了。
添加好後,啟動kernel
列印:
Starting kernel ...
  Linux version 2.6.22.5 (lawrencekang@lawrencekang) (gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72) ) #48 Wed Apr 8 17:40:52 CST 2009
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
Machine: ARM-MYCHIP
Memory policy: ECC disabled, Data cache writeback
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
CPU0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
Built 1 zonelists.  Total pages: 16256
Kernel command line: root=/dev/mtdblock2 rootfstype=yaffs2 console=ttymychip0 mem=64M mtdparts=dwnand:3m(kernel),3m(splash),-(rootfs)
2
PID hash table entries: 256 (order: 8, 1024 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 62616KB available (1992K code, 155K data, 60K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NTFS driver 2.1.28 [Flags: R/W].
io scheduler noop registered (default)
Serial: MYCHIP UART driver
mychipb:1: ttyMYCHIP0 at MMIO 0x5c00000 (irq = 7) is a MYCHIP_UART
Advanced Linux Sound Architecture Driver Version 1.0.14 (Thu May 31 09:03:25 2007 UTC).
ALSA device list:
  No soundcards found.
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
第五步: 添加網卡驅動,以支援NFS
從上面的輸出資訊可以看到,我們的下一步需要掛檔案系統了。
在開發階段,最好用NFS,這需要添加網卡驅動。
需要注意的是sk_buffer ,在老的版本中(比如2.6.17) 有mac,h,nh,而在新的版本中變成了 mac_header ,network_header等。
加好網卡驅動,並在檔案系統中選擇上NFS支援(以及NFS  根檔案系統),編譯後 :
.......
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
IP-Config: Unable to set interface netmask (-22).
Looking up port of RPC 100003/2 on 172.22.1.35
Looking up port of RPC 100005/1 on 172.22.1.35
VFS: Mounted root (nfs filesystem).
Freeing init memory: 76K
Warning: unable to open an initial console.
Kernel panic - not syncing: No init found.  Try passing init= option to kernel.
第六步: 根檔案系統的製作
利用busybox 等製作好rootfs,修改啟動指令碼,也就是在/etc/init.d/rcS中, 加入 echo "hello" ,其他什麼也不作, 在/etc/inittab中,加上:ttyMYCHIP0::respawn:-/bin/sh ,其中ttyMYCHIP 在uart的驅動中定義了。
進入後,就可以 用 ls , cp , ifconfig等命令了 。
第七步: SOC驅動的添加,
1) I2C 驅動

2) SPI 驅動

3)LCD 驅動

4) audio 驅動 ,這個在低的版本中沒有 asoc , 在2.6.22中有asoc

5) Flash驅動 以及 Local File System (Yaffs2 移植 )
6) 

3)

在linux kernel的檔案夾中

/arch 加了一個mach_XXX
/block  unchanged
/Documentation  不用理會
/driver 將 mmc_spi方式移植過來了
驅動中
dwipc
wifi驅動
USB
I2C
SPI
UART
ALSA
NAND
LCD
中斷???

/fs 檔案系統:添加了squashFS
/init : do_mounts_rd.c因為加了squashFS做了相應修改
/ipc : unchanged
/kernel : sched.c 添加了 DPM
/lib : add crc7.c crc-itu-t.c這些都是因為驅動中加了 mmc_spi
/mm  unchanged
/net 很奇怪,這裡也有5個檔案修改了
/scripts :unchanged   
/security unchanged   
/sound      添加了2個裝置的驅動
/usr   unchanged

Makefile 修改了編譯器等

其他都沒變

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.