国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

用網絡卡從并口上啟動Linux

2024-07-21 02:36:00
字體:
來源:轉載
供稿:網友

  作者:raoxianhong
  
  代碼:
  
  1、到底想干什么
   了解linux的啟動過程,制作一個自己的Linux啟動程序,可以增加對Linux的了解,還能學習PC機的啟動機制,增進對計算機結構的了解,增強對Linux內核學習的信心。
  也可以在某些專用產品中使用(比如專用的服務器)。為此,我嘗試在原來代碼的基礎上修改制作了一個用網絡卡從并口上啟動Linux的程序,以博一笑,其中有許多問題值得研究。
  2、Linux對啟動程序的要求
   Linux(bzImage Kernel)對啟動程序的要求比較簡單,你只要能夠建立一個啟動頭(setup.S),
  給出一些信息,然后將kernel(/usr/src/linux/arch/i386/boot/comPRessed/bvmlinux.out)調到
  絕對地址0x100000(1M地址處),假如有initrd,則將它調到內存高端(離0x100000越遠越好,比如假如
  initrd小于4M,就可以將它調到地址0xB00000,即12M處,相信現在已經很少有少于16M內存的機器了),
  然后執行一些初始化操作,跳到內核處就行了。
   當然,說起來輕易做起來還有點麻煩,以下分幾個問題解釋。
  3、PC機開機流程--啟動程序放在何處
   PC機加電后,進入實模式,先進行自檢,然后初始化各個總線擴展設備(ISA, EISA,PCI,AGP),
  全部初始化做完后,從當前啟動設備中讀一個塊(512字節)到07C0:0000處,將控制轉到該處。
   了解這個過程,我們可以決定將啟動程序放在何處:
   1)放在啟動設備的MBR(主啟動記錄中),比如磁盤的啟動扇區。這是一般的啟動方式。
   2)放在總線擴展設備的擴展rom中,比如網卡的boot rom就行,這里制作的啟動程序就是放在網卡中,可以支持 16K字節。
   3)哪位高手能夠修改ROMBIOS,讓BIOS在做完初始化后不要馬上從啟動設備讀數據,而是調用一段外面 加入的程序(2K字節就夠了,當然也必須與修改后的BIOS一起燒在BIOS ROM中),就可以從BIOS啟動!
   4)先啟動一個操作系統,再在此操作系統中寫啟動程序(比如lodlin16就是從DOS中啟動Linux,好象中軟
   提供了一個從Windows下啟動Linux的啟動程序)。
  4、操作系統放在何處
   操作系統(一般內核在500K-1M之間,加上應用程序可以控制在2M以內,當然都經過壓縮了)的數據選擇余地就大了,
  可以從軟盤、硬盤、CDROM、網絡、磁帶機、并口(軟件狗上燒個內核和應用程序?)、串口(外接你的設備)、 USB設備(?)、PCI擴展卡、IC卡等等上面來讀;各位還有什么意見,提醒提醒。有位老兄說實在不行可以用鍵盤啟動,每次啟動時把內核敲進去,還有int 16h支持呢,做起來也不難,應該是最節省的方案了。
   反正一個原則是,在啟動程序中能夠從該設備上讀就行了,這里最簡單的就是并口了,簡單的端口操作,不需 要任何驅動程序支持,不需要BIOS支持,比磁盤還簡單(磁盤一般使用int 13h,主要是計算柱面啊、磁頭啊、磁道啊、扇區啊好麻煩,幸好有現成的源代碼,可以學習學習)。
   好了,我們挑個簡單的方案,將啟動代碼(bootsect.S+setup.S)放到網絡卡的boot rom中,內核數據和應用數據放到另外一臺計算機上,用并口提供。下面談談幾個相關的問題。
  5、將數據移動到絕對地址處
   第一個問題,我們得到數據,因為是在實模式下,所以一般是放在1M地址空間內,怎樣將它移動到指定的地方去,
  在setup.S 的源代碼中,使用了int 15h(87h號功能)。這里將該段代碼稍加改動,做了些假設,列到下面:
  流程是:
   if (%cs:move_es==0)/*由于使用前move_es初始化為0,因此這是第一次調用,此時es:bx是要移動的數據
   存放處bx=0,es低四為位為零表示es:bx在64K邊界上,fs的低8位指定目的地地址,
   也以64K字節為單位,用不著那么精確,以簡化操作*/
   {
   將es右移四位,得到64K單位的8位地址(這樣一來,最多只能將數據移動到16M以下了),作為源數據
   描述符中24位地址的高8位,低16位為零。
   將fs的低8位作為目的地的描述符中24位地址的高8位,同樣,它的低16位為零。
   將es存放在move_es中,es自然不會是零,因此以后再調用該例程時就進行正常的移動操作了。
   ax清零返回。

   }
   else
   {
   if (bx==0)/*bx為零,表示數據已經滿64K了,應該進行實際的移動*/
   {
   調用int15h 87h號功能,進行實際的數據移動(64K, 0x8000個16字節塊)。
   目的地址(24位)高8位增一,往后走64K
   ax = 1
   return;
   }
   else
   {
   ax = 0;
   return;
   }
   }
  # we will move %cx bytes from es:bx to %fs(64Kbytes per unit)
  # when we first call movetohigh(%cs:move_es is zero),
  # the es:bx and %edx is valid
  # we configure the param first
  # follow calls will move data actually
  # %ax return 0 if no data really moved, and return 1 if there is data
  # really to be moved
  #
  movetohigh:
   cmpw $0, %cs:move_es
   jnz move_second
   # at this point , es:bx(bx = 0) is the source address
   # %edx is the destination address
   movb $0x20, %cs:type_of_loader
   movw %es, %ax
   shrw $4, %ax
   movb %ah, %cs:move_src_base+2
   movw %fs, %ax
   movb %al, %cs:move_dst_base+2
   movw %es, %ax
   movw %ax, %cs:move_es
   xorw %ax, %ax
   ret # nothing else to do for now
  move_second:
   xorw %ax, %ax
   testw %bx, %bx
   jne move_ex
   pushw %ds
   pushw %cx
   pushw %si
   pushw %bx
   movw $0x8000, %cx # full 64K, INT15 moves Words
   pushw %cs
   popw %es
   leaw %cs:move_gdt, %si
   movw $0x8700, %ax
   int $0x15
   jc move_panic # this, if INT15 fails
   movw %cs:move_es, %es # we reset %es to always point
   incb %cs:move_dst_base+2 # to 0x10000
   popw %bx
   popw %si
   popw %cx
   popw %ds
   movw $1, %ax
  move_ex:
   ret
  move_gdt:
   .word 0, 0, 0, 0
   .word 0, 0, 0, 0
  move_src:
   .word 0xffff
  move_src_base:
   .byte 0x00, 0x00, 0x01 # base = 0x010000
   .byte 0x93 # typbyte
   .word 0 # limit16,base24 =0
  move_dst:
   .word 0xffff
  move_dst_base:
   .byte 0x00, 0x00, 0x10 # base = 0x100000
   .byte 0x93 # typbyte
   .word 0 # limit16,base24 =0
   .word 0, 0, 0, 0 # BIOS CS
   .word 0, 0, 0, 0 # BIOS DS
  move_es:
   .word 0
  move_panic:
   pushw %cs
   popw %ds
   cld
   leaw move_panic_mess, %si
   call prtstr
  move_panic_loop:
   jmp move_panic_loop
  move_panic_mess:
   .string "INT15 refuses to access high mem, giving up."
  6、用并口傳輸數據
   用并口傳輸數據,可以從/usr/src/linux/driver/net/plip.c中抄一段,我們采用半字節協議,
  并口線連接參考該文件。
字節收發過程如下:
  #define PORT_BASE 0x378
  #define data_write(b) outportb(PORT_BASE, b)
  #define data_read() inportb(PORT_BASE+1)
  #define OK 0
  #define TIMEOUT 1
  #define FAIL 2
  
  int sendbyte(unsigned char data)
  {
   unsigned char c0;
   unsigned long cx;
   data_write((data & 0x0f));
   data_write((0x10 (data & 0x0f)));
   cx = 32767l * 1024l;
   while (1) {
   c0 = data_read();
   if ((c0 & 0x80) == 0)
   break;
   if (--cx == 0)
   return TIMEOUT;
   }
   data_write(0x10 (data >> 4));
   data_write((data >> 4));
   cx = 32767l * 1024l;
   while (1) {
   c0 = data_read();
   if (c0 & 0x80)
   break;
   if (--cx == 0)
   return TIMEOUT;
   }
   return OK;
  }
  int rcvbyte(unsigned char * pByte)
  {
   unsigned char c0, c1;
   unsigned long cx;
   cx = 32767l * 1024l;
   while (1) {
   c0

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 清河县| 临洮县| 建宁县| 四子王旗| 图木舒克市| 故城县| 宁强县| 新余市| 敖汉旗| 宜宾县| 区。| 东阿县| 上饶县| 重庆市| 西贡区| 义马市| 衡阳市| 友谊县| 江陵县| 常山县| 永平县| 丰城市| 弥勒县| 稷山县| 平潭县| 清流县| 舟山市| 全椒县| 紫金县| 新化县| 赤水市| 精河县| 新晃| 巴里| 葵青区| 大冶市| 青川县| 应城市| 宾阳县| 张掖市| 阿拉尔市|