  Rgǂ Linux J[l
  Sano Taketoshi <kgh12351@nifty.ne.jp>
  $Date: 2000/06/27 13:57:52 $

  NLUG (É Linux [U[O[v)  3 ׋̂߂ɍ쐬
  łB ǂނ̂ Linux J[l 2.2.5 łB PC/AT (i386) 
  ŁAd ON ̂ƁAJ[l̃[hA u[gAbv /sbin/init 
  s܂ł\[XR[h̃Rg𗊂ɒǂĂ܂B
  ______________________________________________________________________

  ڎ

  1. ͂߂
     1.1 uJ[lvƂ
     1.2 Linux J[l
     1.3 R[h쐬ɍvlX
     1.4 S҈ꗗ

  2. VXe̋NFTv
     2.1 J[l̃[h
     2.2 BIOS ̎擾
     2.3 J[l{̂̓WJ
     2.4 foCXhCo[̐ݒ
     2.5 init ̋N
     2.6 VXeN

  3. J[l̃[h
     3.1 bootsect.S - `̃Rg
     3.2 bootsect.S - p[^`
     3.3 bootsect.S - ۂ̓

  4. BIOS ̎擾
  5. J[l{̂̓WJ
  6. foCXhCo[̐ݒ
  7. init ̋N
  8. ԊO: Makefile ɂ
  9. I
     9.1 肢
     9.2 ӎ
     9.3 ̔̕zzɂ

  ______________________________________________________________________

  1.  ͂߂

  1.1.  uJ[lvƂ

  ԂAx炢ǂŖڂɂƂ邩܂񂪁uLinuxv
  ƂO͓tBh̑wł Linus Torvalds 񂪎
  ̍uJ[lvɁA̖OꕔĕtOłB

  āAŖBuJ[lvĉł傤 ?

  uJ[lvƂ́AVXeœ쒆̊evOovɉ
  ă[fBXNȂǂ̃n[hEFÅǗA CPU Ԃ̔z
  ȂǂsȂ OS ̒łB

  Ⴆ "top" R}hsĂ΂炭߂ĂƁAXgĂ
  vZX̏ԂXւ邱Ƃ̂ɋCÂł傤B́u
  ̓ւv̓J[l̃^XNǗ (XPW[O) ɂ̂łB
  ܂Av^ڑĈł悤ɐݒ肷ہA

       cat test.pr >/dev/lp0

  Ȃǂ̑ɂăp|[gւ̐Mo͂eXgo͂܂
   ?  ́u /dev/lp0 ɏo͂f[^͂̂܂܃p|[gɏo
  vƂ̓J[l lp hCoɂĎĂ܂B

  1.2.  Linux J[l

  ȉA̕ł Linux J[l̃\[XR[hc[ARg
  ɂĂƂTĂ݂邱Ƃɂ܂B

  ܂́Ao[W 2.2.5 ̃J[lWJāÃgbvfBNg
  ɈړĂ݂܂傤BAʏ /usr/src/linux/ ƂČ邱Ƃł
  ꏊłB

  ܂͂ǂȃt@C邩A "ls" ŒׂĂ݂܂B

        $ ls -F
        COPYING         Makefile        arch/           init/           mm/
        CREDITS         README          drivers/        ipc/            net/
        Documentation/  REPORTING-BUGS  fs/             kernel/         scripts/
        MAINTAINERS     Rules.make      include/        lib/

  ŏɓǂłׂt@C "README" łˁB̓J[lłȂ
  Aʂ̃AvP[Ṽ\[XłłBAł͂̃t@C
  ̓eɂĂ͏ȗāȂ "CREDITS"  "MAINTAINERS" 
   2 ̃t@C̓eɂďЉƎv܂B

  1.3.  R[h쐬ɍvlX

  "CREDITS" t@C̖`ɂ

          This is at least a partial credits-file of people that have
          contributed to the Linux project.  It is sorted by name and
          formatted to allow easy grepping and beautification by
          scripts.  The fields are: name (N), email (E), web-address
          (W), PGP key ID and fingerprint (P), description (D), and
          snail-mail address (S).
          Thanks,

                          Linus

  ƏĂ܂B̃t@Cɂ Linux J[l̊JɍvlX
  (̈ꕔ) ̖OĂAƂ킯łB

  Ⴆ΁A TV ̓WŎނĂ{̐V̖O

        N: Niibe Yutaka
        D: PLIP driver
        D: Asynchronous socket I/O in the NET code

  ƋLڂĂ܂BALinus ̖O

        N: Linus Torvalds
        D: Original kernel hacker

  ƂڂĂ܂A ac pb`ŗL Alan Cox  fat32 Ή
   Gordon ChaffeeAɈȑO Linux Kernel  Sound Driver 
  Ă OpenSoundSystem  Hannu Savolainen ̖O܂B

        N: Alan Cox
        D: Linux Networking (0.99.10->2.0.29)
        D: Original Appletalk, AX.25, and IPX code
        D: Current 3c501 hacker. >>More 3c501 info/tricks wanted<<.
        D: Watchdog timer drivers
        D: Linux/SMP x86 (up to 2.0 only)
        D: Initial Mac68K port
        D: Video4Linux design, bw-qcam and PMS driver ports.
        D: 2.1.x modular sound

        N: Gordon Chaffee
        D: vfat, fat32, joliet, native language support

        N: Hannu Savolainen
        D: Kernel sound drivers

  ɂASlackware  Patrick VolkerdingA Debian  Ian A. Murdock 
  Ian Jackson Aɂ낢ƊeʂŗL Eric S. Raymond 
  XFree86  Dirk Hohndel (ނ TV ŎނĂ܂)  Harald
  Koenig ̖O܂ALDP ֌W҂ł Michael K. Johnson  Matt
  Welsh ڂĂ܂B

        N: Patrick Volkerding
        D: Produced the Slackware distribution, updated the SVGAlib
        D: patches for ghostscript, worked on color 'ls', etc.

        N: Ian A. Murdock
        D: Creator of Debian distribution

        N: Ian Jackson
        D: FAQ maintainer and poster of the daily postings
        D: FSSTND group member
        D: Debian core team member and maintainer of several Debian packages

        N: Eric S. Raymond
        D: terminfo master file maintainer
        D: Editor: Installation HOWTO, Distributions HOWTO, XFree86 HOWTO
        D: Author: fetchmail, Emacs VC mode, Emacs GUD mode

        N: Dirk Hohndel
        D: The XFree86[tm] Project

        N: Harald Koenig
        D: XFree86 (S3), DCF77, some kernel hacks and fixes

        N: Michael K. Johnson
        D: The Linux Documentation Project
        D: Kernel Hackers' Guide
        D: Procps
        D: Proc filesystem
        D: Maintain tsx-11.mit.edu
        D: LP driver

        N: Matt Welsh
        D: Linux Documentation Project coordinator
        D: Author, _Running_Linux_ and I&GS guide
        D: Linuxdoc-SGML formatting system
        D: Keithley DAS1200 device driver
        D: Maintainer of sunsite WWW and FTP, moderator c.o.l.answers

   " egrep '^N:' CREDITS |wc" ƂĐĂ݂ƂA2.2.5 J[
  l CREDITS t@Cɂ͂ 273 l̖OĂ悤
  B(2.0.36 ŒׂĂ݂ 204 lł) ̒ɏĂ閼O
  lmĂ邩AĂ݂ Linux Eւ̃n}x킩Ă낢
  ܂B

  AuRgvɂ̂ƂẮÃt@C̍Ō
  Ȃ悤ɂĂƂKvłB

        # Don't add your name here, unless you really _are_ after Marc
        # alphabetically. Leonard used to be very proud of being the
        # last entry, and he'll get positively pissed if he can't even
        # be second-to-last.  (and this file really _is_ supposed to be
        # in alphabetic order)

  "pissed off" Ă̂́Au{vƂuɂvƂӖ
  łˁBĂAJ[lJ҂lԂȂ񂾂ȁAƂ
  Ĕ΂܂C܂B

  ƁAЂƂYĂ܂BłB

        N: Lars Wirzenius
        D: Linux System Administrator's Guide
        D: Co-moderator, comp.os.linux.announce
        D: Original sprintf in kernel
        D: Personal information about Linus
        D: Original kernel README
        D: Linux News (electronic magazine)
        D: Meta-FAQ, originator
        D: INFO-SHEET, former maintainer
        D: Author of the longest-living linux bug

  Ō̍sɒڂĂBȂȂ[Â̂悤łB

  ʁuoOꂽvƂ̂́A܂莩ł邱Ƃł͂Ȃ
  ŁAR[hJւ̍vɎӈӂ\邽߂́uv CREDITS ɍڂ
  ȂƂ͂܂肵ȂƎv̂łAL̕킴킴ĂƂ
  ̂́AԂ񂱂 Wirzenius 񂪎ŁuĂvƈ˗
  񂶂ȂƑzĂ܂B

  Ĺuł̂тoO̒ҁvƂ́AʏȂ炠܂
  \ȂƎv悤ȉߋ́uoOv̂ƂłAu΂v̑Ώۂɂ
  Ă܂ƂoC^eBƂA[ÃZX܂Bu
   ? ̗̉LȁwłꂸɎcoOx̒҂
  񂾂 ! XSC낤 !!v݂ȊłˁB

  1.4.  S҈ꗗ

  āA낻뎟Ɉڂ܂傤Bx "MAINTAINERS" t@CłB
  ̃t@C̖`ɂ

                List of maintainers and how to submit kernel changes

        Please try to follow the guidelines below.  This will make things
        easier on the maintainers.  Not all of these guidelines matter for every
        trivial patch so apply some common sense.

  ƏĂ܂B܂{Iɂ Linux J[l̎ŕύX
  yސl (J[lnbJ[) ΏۂɁÃpb`ǂɑΕWƂ
  č̗p̂AƂ菇̂łB

  Ãt@Cɂ͊y߂_̂łB͂̃t@C
  ̈ԍŌB

        THE REST
        P:      Linus Torvalds
        S:      Buried alive in reporters

  Ȃ݂ɁA2.0.36 ܂ł 2.0.xx nł͂ȂĂ܂B

        REST:
        P:      Linus Torvalds
        S:      Buried alive in email

  N Linux  Linus 芪󋵂̕ω𕨌Ă悤
  B

  2.  VXe̋NFTv

  ł̓VXe̓d ON  /sbin/init N܂ł̗
  ɐ܂B

  2.1.  J[l̃[h

  PC/AT ݊@ł̓}U[{[h BIOS su[gV[PXɂ
  NfBXÑu[gZN^ɏ܂ĂR[h̃[ʒu
  փ[hÃR[hs ([hR[h̊Jnʒu jump) 
  B

  (ũ[ʒuvƂ segment 0h / address 7C00h ܂
  [0000:7C00] łALinux J[l̒ł offset  0 n߂
  悤 segment  7C0 ɂĂ炵Ƃ𒸂܂B)

  PC ŗpe OS ́A BIOS ɂu[gOƂāAŏ
  Ǎ܂R[hn܂ďɎ傫R[h[hAŏII
  ɕKvȃR[hׂă[ɓǂݍŎsJnƂs
  ȂĂ܂B

  ̈A̓ʂɃu[gXgbvAƌĂт܂Bu[g boot (
  C)AXgbv strap (vR) ̂ƂŁAĂ钷C̕R
  ňđ̂グ悤Ƃ邱ƂɗႦĂ܂B

  ȂuBootstrapvɂẲ
  http://www.oreilly.com/reference/dictionary/terms/B/Bootstrap.htm
  <http://www.oreilly.com/reference/dictionary/terms/B/Bootstrap.htm>

  ɂ܂̂ŁÂׂ͒Ă݂邱Ƃ߂܂BȂ
  Web y[Wɂ́u"Bootstrap" ̂Ƃ IBM p IPL, Initial Program
  Load ƌĂԁvƏĂ܂B

  Linux J[l̓ɂ́A(炽߂ĕƋ邩܂)
  ȂƂ i386 nł̓n[hfBXN玩OŃu[g邽߂̃R[
  h͗pӂĂ܂Bn[hfBXÑu[gł LILO  LOADLIN
  Ȃǂ̃u[g[_[𗘗p邱ƂOƂȂĂ܂B

  tbs[̋N̏ꍇAJ[lōŏɃ[hR[h
  arch/i386/boot/bootsect.S łB̃R[h͓fBNgɂ
  arch/i386/boot/setup.S ̃R[hƁAJ[l̎c[h setup.S
  ɐڍs܂B

  2.2.  BIOS ̎擾

  arch/i386/boot/setup.S ̓[TCYfBXNA܂R\[
  prfIJ[h̏ APM BIOS ̃`FbNȂǁAVXeɊւ邢낢
  ȏ BIOS 擾āAŃfoCXhCo[ۂɎg
  pł悤A[ɕۑ܂B

   LILO Ȃǂ̃u[g[_[gpꍇɂ́ANɃL[{[h
  ͂ꂽJ[lIvVŎQƂł悤Ƀ[̓
  ̏ꏊɃRs[̂ setup.S ̎dłB

  setup.S  BIOS ̎擾ƁACPU ̃[hN 16bit
  [h 32bit (protected) [hɐ؂ւāA
  arch/i386/boot/compressed/head.S ɏڍs܂B

  2.3.  J[l{̂̓WJ

  arch/i386/boot/compressed/head.S ͂̃`FbN SMP ̏ꍇɕK
  vȏsŁAfBNgɑ݂
  arch/i386/boot/compressed/misc.c Œ`ꂽ decompress_kernel() Ƃ
  ֐gāA gzip kꂽԂŃ[Ƀ[hĂJ[l
  {̂WJ܂B

  R\[j^[

       Uncompressing Linux...

  Ƃ\o͂̂́A decompress_kernel() ̎słB

  WJIƁAarch/i386/boot/compressed/head.S ͐V[
  Ɍꂽ{̃J[lR[hւƏڍs܂B

  2.4.  foCXhCo[̐ݒ

  arch/i386/boot/compressed/head.S ɂēWJꂽu{̃J[lR
  [hv̐擪ɑ݂Ă̂ arch/i386/kernel/head.S łB

  ̃R[h͎ CPU Ɋւ鏉 (y[We[ȕ⊄荞
  (C^vg) e[ȕȂ) sAŌ init/main.c ɂ
   start_kernel() s܂B

   start_kernel() ł͂܂łɃVXeW߂ĂāA[
  ʒuɕۑĂ邢낢ȏgāA[Ǘ^XNX
  PW[Ɋ֘AJ[l̊efoCXhCo[ݒ肵Ă
  B܂R\[o͂̐ݒŝ start_kernel() łB

  start_kernel() ͓ init/main.c ɂ init()  kernel_thread () 
  gċNA͂蓯 init/main.c ɂ cpu_idle() s
  B cpu_idle()  arch/i386/kernel/process.c ̒Œ`Ă
  sys_idle() s閳[vłB

  āAstart_kernel()  kernel_thread() oRċNꂽ
  init/main.c Œ`Ă init() łAŏ lock_kernel() (
   SMP ̏ꍇɂ݈̂Ӗ܂) sƁAdo_basic_setup() 
  s܂B

   do_basic_setup()  init/main.c ̒Œ`Ă܂AoX
  efoCXhCȍAt@CVXe֘AR[h̏
  A[gt@CVXẽ}EgȂǂŎsĂ܂BȂ
  ɁȀ 2.0.36 ł start_kernel() ̓ŎsĂ܂
  B2.2.xx nɂȂĈڐA߂邽߂Â̏ɍ
  R[h̍\ύXꂽ悤łB

  2.5.  init ̋N

  init/main.c Œ`Ă init()  do_basic_setup() 珈߂
  ĂƁANɂ̂ݕKvƂꂽ[̈̊JƃR\[o͂
  I[vsA

       /sbin/init, /etc/init, /bin/init, /bin/sh

  ԂɎāAŏɌs\Ȃ̂ւƏڍs܂B

  2.6.  VXeN

  ȍ~̏́A/etc/inittab ł̐ݒ /etc/rc.d ܂ /etc/init.d
   /etc/rc?.d ɂNXNvg̐ݒȂǂɂē삪܂܂B
  ɂẮAԂɂm̂̂ł͂Ȃł傤B

  uJ[l̋NvɂĂ̊Tv͂ŏIłB̐߂Aɏq
  ׂeiKŎgpR[hɂăRg𗊂ɒׂĂƂɂ
  ܂B

  3.  J[l̃[h

  ĹuTvvŐ悤ɁAtbs[̋N̏ꍇAJ[l
  ōŏɃ[hR[h arch/i386/boot/bootsect.S łB

  ܂́Ãt@C璭߂Ă݂邱Ƃɂ܂傤B

  3.1.  bootsect.S - `̃Rg

  !
  !       bootsect.s              Copyright (C) 1991, 1992 Linus Torvalds
  !       modified by Drew Eckhardt
  !       modified by Bruce Evans (bde)
  !
  ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
  ! itself out of the way to address 0x90000, and jumps there.
  !
  ! bde - should not jump blindly, there may be systems with only 512K low
  ! memory.  Use int 0x12 to get the top of memory, etc.
  !
  ! It then loads 'setup' directly after itself (0x90200), and the system
  ! at 0x10000, using BIOS interrupts.
  !
  ! NOTE! currently system is at most (8*65536-4096) bytes long. This should
  ! be no problem, even in the future. I want to keep it simple. This 508 kB
  ! kernel size should be enough, especially as this doesn't contain the
  ! buffer cache as in minix (and especially now that the kernel is
  ! compressed :-)
  !
  ! The loader has been made as simple as possible, and continuous
  ! read errors will result in a unbreakable loop. Reboot by hand. It
  ! loads pretty fast by getting whole tracks at a time whenever possible.

  ́uTvvɏƂA`ɃRgƂċLڂĂ
  ˁB

  ubootsect.s  BIOS ̃u[gV[PXɂă[̃AhX
  0x7c00 Ƀ[hB bootsect.s ͎gAhX 0x90000 
  ړAĂփWv (ڍs) Bv

  ЂƂ΂

  uɎg̒ (0x90200)  'setup' A܂VXe 0x10000
   BIOS C^vggă[hv

  ̎ƂȂĂ͎RgłˁB

  u! ݁AVXe͍őł (8*65536-4096) oCg܂ł̒ł
  B̐ɂẮAႦɂĂA𐶂邱Ƃ͖B
  ͂ȂׂPɂĂ̂B̃J[lTCY 508 kB Ƃ
  ́Aminix ̂悤Ƀobt@[LbV܂ł킯ł͂Ȃ
  l (Ă܂A݃J[l͈kꂽԂŃ[hĂ
  Ƃl :) ܂\ȑ傫ƌ͂łBv

  ۂɂ͐NOɂ́u508kB ̕ǁv͏\Ƃ͌ȂȂĂ
  AbZimage ƂpӂĂ܂BÂ߂Ɂu
  ȂׂPɁvƂ Linus ̊]ۂ̃R[h◣Ă܂
  悤Ɋ܂B

  3.2.  bootsect.S - p[^`

  낻AR[h̒gɓĂ݂܂傤B

  #include <linux/config.h> /* for CONFIG_ROOT_RDONLY */
  #include <asm/boot.h>

  .text

  SETUPSECS = 4                           ! default nr of setup-sectors
  BOOTSEG   = 0x07C0                      ! original address of boot-sector
  INITSEG   = DEF_INITSEG                 ! we move boot here - out of the way
  SETUPSEG  = DEF_SETUPSEG                ! setup starts here
  SYSSEG    = DEF_SYSSEG                  ! system loaded at 0x10000 (65536).
  SYSSIZE   = DEF_SYSSIZE                 ! system size: number of 16-byte clicks

  ŏ̍sA#include <linux/config.h>  include/linux/config.h ̒`
  gAƂƂłBŁÃwb_[t@C̒g͂ȂĂ܂B

  #ifndef _LINUX_CONFIG_H
  #define _LINUX_CONFIG_H

  #include <linux/autoconf.h>

  #endif

  ꂾB include/linux/autoconf.h ̒`gȂAƂ
  ƂłBŁÃt@CTĂ݂ƁA܂B

  ͂ autoconf.h  make config / menuconfig / xconfig Ȃǂs
  Ďn߂č쐬t@CłāAPɃA[JCuWJł͑
  ݂Ȃ̂łB

  ͎Ԃ̓sŁÃt@C菇ǂ̂͏ȗA
   #include <asm/boot.h> 𒲂ׂĂ݂邱Ƃɂ܂B

   include/asm-i386/boot.h TĂt@C

  #ifndef _LINUX_BOOT_H
  #define _LINUX_BOOT_H

  /* Don't touch these, unless you really know what you're doing. */
  #define DEF_INITSEG     0x9000
  #define DEF_SYSSEG      0x1000
  #define DEF_SETUPSEG    0x9020
  #define DEF_SYSSIZE     0x7F00

  /* Internal svga startup constants */
  #define NORMAL_VGA      0xffff          /* 80x25 mode */
  #define EXTENDED_VGA    0xfffe          /* 80x50 mode */
  #define ASK_VGA         0xfffd          /* ask for it at bootup */

  #endif

  ƏĂ܂B̂A2.0.36 ƔrĕύXꂽł
  ˁB (2.0.36 ł͂̒` include/linux/config.h ɂ܂)

  āAbƂ bootsect.S ɖ߂܂B

  .text

  SETUPSECS = 4                           ! default nr of setup-sectors
  BOOTSEG   = 0x07C0                      ! original address of boot-sector
  INITSEG   = DEF_INITSEG                 ! we move boot here - out of the way
  SETUPSEG  = DEF_SETUPSEG                ! setup starts here
  SYSSEG    = DEF_SYSSEG                  ! system loaded at 0x10000 (65536).
  SYSSIZE   = DEF_SYSSIZE                 ! system size: number of 16-byte clicks

  ̍̕ŏɂ ".text" ́AReLXgƂӖŎsR[h
  JnʒuĂ܂B

  ŏA͂玟".globl  _main" ܂ł́uϐv̒`ƎvĂ
  ̂łAł͂ȂāAAZu (@Bɖ|) ۂɐlɕ
  ăR[hɑu萔`v(C  #define Œ`}N
  Ɏ) ƍlقǂƋ܂B

  ŎQƂĂ

       DEF_INITSEG, DEF_SETUPSEG, DEF_SYSSEG, DEF_SYSSIZE

  ͊ɌĂ悤ɁAinclude/asm/boot.h Œ`Ă܂B

  ̉̕ɂA萔̒`Ă܂AȗĎɐi
  ܂B

  3.3.  bootsect.S - ۂ̓

   ".globl  _main" ȍ~ۂɓ삷ۂɎgR[hn܂
  Ă܂B

  ! ld86 requires an entry symbol. This may as well be the usual one.
  .globl        _main
  _main:
  #if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
          int     3
  #endif
          mov     ax,#BOOTSEG
          mov     ds,ax
          mov     ax,#INITSEG
          mov     es,ax
          mov     cx,#256
          sub     si,si
          sub     di,di
          cld
          rep
          movsw
          jmpi    go,INITSEG

  ! ax and es already contain INITSEG

   "#BOOTSEG"  BIOS ɂ bootsect.S ̃R[h[hꂽA
  hXA"#INITSEG"  bootsect.S gRs[ďڂ(W
  v) AhXłBł "movsw" ܂ł̍sŁug̃Rs
  [vsA"jmpi"  "#INITSEG" ɃRs[ꂽg "go" x
  ̈ʒuփWvĂ܂B

  ̂Ƃ΂炭tbs[hCu܂삳邽߂̏sȂ
  ܂BĎ "load_setup"  setup.S ̃R[h[hĂ
  ܂B

  load_setup:
          xor     ah,ah                   ! reset FDC
          xor     dl,dl
          int     0x13

  ŏ̓tbs[hCuRg[ZbgƂ납n܂

          xor     dx, dx                  ! drive 0, head 0
          mov     cl,#0x02                ! sector 2, track 0
          mov     bx,#0x0200              ! address = 512, in INITSEG
          mov     ah,#0x02                ! service 2, nr of sectors
          mov     al,setup_sects          ! (assume all on head 0, track 0)
          int     0x13                    ! read it
          jnc     ok_load_setup           ! ok - continue

  hCuAwbhAZN^[AgbNȂǂ̈ʒuAǂݏoAh
  Xw肵 "int   0x13" ̎sɂ BIOS ̃ZN^[ǂݍ݋@\
  𗘗p "setup.S" ̃R[h[Ƀ[hĂ܂B[h
  ̃AhX "INITSEG" ̃AhX 0x9000  0x200  0x9200 Ƃ
  ܂B

  setup.S ̃[h "Loading" ƂbZ[W\āA
  ̒iK (kꂽVXe{̂̃[h) ւƐi݂܂B

  got_sectors:

  ! Restore es

          mov     ax,#INITSEG
          mov     es,ax

  ! Print some inane message

          mov     ah,#0x03                ! read cursor pos
          xor     bh,bh
          int     0x10

          mov     cx,#9
          mov     bx,#0x0007              ! page 0, attribute 7 (normal)
          mov     bp,#msg1
          mov     ax,#0x1301              ! write string, move cursor
          int     0x10

  ! ok, we've written the message, now
  ! we want to load the system (at 0x10000)

          mov     ax,#SYSSEG
          mov     es,ax           ! segment of 0x010000
          call    read_it
          call    kill_motor
          call    print_nl

   "int  0x10" ͉ʕ\ BIOS C^vgłA "#msg1" 
  bootsect.S ̏Îق

            msg1:
                    .byte 13,10
                    .ascii "Loading"

  ƂĒ`Ă܂B ".byte"  13  CR (LbW^[
  )A 10 LF (CtB[h) łB

  āAVXe{̂̃[hłA͏ɏꂽ "call  read_it"
  ČĂяo

  ! This routine loads the system at address 0x10000, making sure
  ! no 64kB boundaries are crossed. We try to load it as fast as
  ! possible, loading whole tracks whenever we can.
  !
  ! in:   es - starting address segment (normally 0x1000)
  !
  sread:  .word 0                       ! sectors read of current track
  head:   .word 0                       ! current head
  track:  .word 0                       ! current track

  read_it:

  ȍ~̕AɎ rp_read: n܂镔ɂ܂B

  rp_read:
  #ifdef __BIG_KERNEL__
  #define CALL_HIGHLOAD_KLUDGE .word 0x1eff,0x220 ! call far * bootsect_kludge
                                  ! NOTE: as86 can't assemble this
          CALL_HIGHLOAD_KLUDGE    ! this is within setup.S
  #else
          mov ax,es
          sub ax,#SYSSEG
  #endif
          cmp ax,syssize          ! have we loaded all yet?
          jbe ok1_read
          ret

   "CALL_HIGHLOAD_KLUDGE" ̓Rgɂ悤ɂ傤ǂ̕
  OɃ[h setup.S ̃R[hɊ܂܂Ă bootsect_kludge 
  ΉAhXn܂R[hłB setup.S ̒ł
  "bootsect_kludge" ͎̂悤ɒ`Ă܂B

  bootsect_kludge:
                  .word   bootsect_helper,SETUPSEG

  ܂ bootsect_helper  setup.S ̒ňȉ̂悤ɒ`Ă
  B

  ! This routine only gets called, if we get loaded by the simple
  ! bootsect loader _and_ have a bzImage to load.
  ! Because there is no place left in the 512 bytes of the boot sector,
  ! we must emigrate to code space here.
  !
  bootsect_helper:

  Rgɂubootsect.S ɂ bzImage `̃J[l[h
  ꂽꍇɌĎsAƏĂ܂ˁB

  āAbootsect.S ̒ŁAۂɃtbs[VXeǂł
  ́Aȉ̕łB

  read_track:
          pusha
          pusha
          mov     ax, #0xe2e      ! loading... message 2e = .
          mov     bx, #7
          int     0x10
          popa

   0x10 ͉ʕ\sȂ BIOS C^vgR[łB
  setup.S ̃R[h[h_ŁA "Loading" ƂbZ[W
  ɏo͂Ă͂Ȃ̂ŁAł "." ̏o݂͂̂sȂĂ܂B

          mov     dx,track
          mov     cx,sread
          inc     cx
          mov     ch,dl
          mov     dx,head
          mov     dh,dl
          and     dx,#0x0100
          mov     ah,#2

          push    dx                              ! save for error dump
          push    cx
          push    bx
          push    ax

          int     0x13
          jc      bad_rt
          add     sp, #8
          popa
          ret

  BIOS C^vg "Int 0x13" ̎sɂătbs[̃VXet@
  C[Ƀ[hĂ܂B

  [hƁAɈp

          call    read_it
          call    kill_motor
          call    print_nl

  Ɏsătbs[hCũ[^[ OFF ɂAʂɉsR[
  h (NewLine) o͂܂B

  ̌A[gfoCX̃`FbNo

  ! after that (everything loaded), we jump to
  ! the setup-routine loaded directly after
  ! the bootblock:

          jmpi    0,SETUPSEG

  "SETUPSEG" ɑ݂ setup.S ̃R[hɃWv܂B

  4.  BIOS ̎擾

  āAarch/i386/boot/setup.S ɐi݂܂傤B

  ܂̓t@C`̃RgB

  !
  !       setup.S         Copyright (C) 1991, 1992 Linus Torvalds
  !
  ! setup.s is responsible for getting the system data from the BIOS,
  ! and putting them into the appropriate places in system memory.
  ! both setup.s and system has been loaded by the bootblock.
  !
  ! This code asks the bios for memory/disk/other parameters, and
  ! puts them in a "safe" place: 0x90000-0x901FF, ie where the
  ! boot-block used to be. It is then up to the protected mode
  ! system to read them from there before the area is overwritten
  ! for buffer-blocks.
  !
  ! Move PS/2 aux init code to psaux.c
  ! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
  !
  ! some changes and additional features by Christoph Niemann,
  ! March 1993/June 1994 (Christoph.Niemann@linux.org)
  !
  ! add APM BIOS checking by Stephen Rothwell, May 1994
  ! (Stephen.Rothwell@canb.auug.org.au)
  !
  ! High load stuff, initrd support and position independency
  ! by Hans Lermen & Werner Almesberger, February 1996
  ! <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
  !
  ! Video handling moved to video.S by Martin Mares, March 1996
  ! <mj@k332.feld.cvut.cz>
  !
  ! Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
  ! parsons) to avoid loadlin confusion, July 1997

  ǂł傤 ? ̃Rgǂ߂΁Ãt@CɏĂ
  R[hĂ̂A킩悤ȋCɂȂ܂ ?

  vɁusetup.S  BIOS VXeɊւf[^擾AVXe
  [̓K؂ȏꏊɕۊǂ邽߂̃R[hłBvƂƂłB

  ܂Aꂾł͂܂Ȃ̂ŁAƖʔȂƂ𔲂o
  ݂ƁA

  ! SETUP-header, must start at CS:2 (old 0x9020:2)
  !
                  .ascii        "HdrS"              ! Signature for SETUP-header
                  .word 0x0201          ! Version number of header format
                                          ! (must be >= 0x0105
                                          ! else old loadlin-1.5 will fail)
  realmode_swtch: .word 0,0             ! default_switch,SETUPSEG
  start_sys_seg:  .word SYSSEG
                  .word kernel_version  ! pointing to kernel version string
    ! note: above part of header is compatible with loadlin-1.5 (header v1.5),
    !        must not change it

  type_of_loader: .byte 0               ! = 0, old one (LILO, Loadlin,
                                          !      Bootlin, SYSLX, bootsect...)
                                          ! else it is set by the loader:
                                          ! 0xTV: T=0 for LILO
                                          !       T=1 for Loadlin
                                          !       T=2 for bootsect-loader
                                          !       T=3 for SYSLX
                                          !       T=4 for ETHERBOOT
                                          !       V = version
  loadflags:                      ! flags, unused bits must be zero (RFU)
  LOADED_HIGH     = 1             ! bit within loadflags,
                                  ! if set, then the kernel is loaded high
  CAN_USE_HEAP    = 0x80          ! if set, the loader also has set heap_end_ptr
                                  ! to tell how much space behind setup.S
                                  | can be used for heap purposes.
                                  ! Only the loader knows what is free!
  #ifndef __BIG_KERNEL__
                  .byte 0x00
  #else
                  .byte LOADED_HIGH
  #endif

  "type_of_loader" ̂Ƃ
   LILO, Loadlin, bootsect-loader, SYSLX, ETHERBOOT XgĂ
  B Linux ̃J[l[_[\ނ܂ˁB

  ̍ŏ̕ł̓[_[̃`FbNĂ܂BÂ[_[ł
  "big kernel" ܂Ȃ߁Aꍇɂ͌x𔭂Ď~
  ɂȂĂ܂B

  [_[̃`FbNIƁA[TCỸ`FbNn܂܂B

  loader_ok:
  ! Get memory size (extended mem, kB)

  #ifndef STANDARD_MEMORY_BIOS_CALL
          push    ebx

          xor     ebx,ebx         ! preload new memory slot with 0k
          mov     [0x1e0], ebx

          mov     ax,#0xe801
          int     0x15
          jc      oldstylemem

  "int 0x15"  #0xe801 gݍ킹ă[TCY`FbNĂ
  B

  ! Memory size is in 1 k chunksizes, to avoid confusing loadlin.
  ! We store the 0xe801 memory size in a completely different place,
  ! because it will most likely be longer than 16 bits.
  ! (use 1e0 because that's what Larry Augustine uses in his
  ! alternative new memory detection scheme, and it's sensible
  ! to write everything into the same place.)

  ̓L[{[hs[g[g̐ݒłB

  ! Set the keyboard repeat rate to the max

          mov     ax,#0x0305
          xor     bx,bx           ! clear bx
          int     0x16

  ăR\[prfIJ[h̃`FbNB

  ! Check for video adapter and its parameters and allow the
  ! user to browse video modes.

          call    video   ! NOTE: we need DS pointing to boot sector

   "call video" ŌĂяoĂ͓̂fBNgɂ
  arch/i386/boot/video.S ̒Œ`Ă֐łB

  ȌAen[hEFA`FbNĂ镔ŁARgEĂ
  ( [] ̓Rga󂵂̂ł)

  ! Get hd0 data
      [hd0 ̃f[^擾]

  ! Get hd1 data
      [hd1 ̃f[^擾]

  ! Check that there IS a hd1 :-)
      [hd1 ڑĂ邩ǂ`FbN]

  ! check for Micro Channel (MCA) bus
      [}CN`l (MCA) oX`FbN]

  ! Check for PS/2 pointing device
      [PS/2 ̃|C^u (}EXApbhAXeBbNȂ) `FbN]

  #ifdef CONFIG_APM
  ! check for APM BIOS
      [APM BIOS `FbN]

  !
  ! Redo the installation check as the 32 bit connect
  ! modifies the flags returned on some BIOSs
  !

      [32bit ŐڑƃtbO̒lύX BIOS ̂
      CXg[V`FbNēxs]

  done_apm_bios:
  #endif

  Ȃǂ̏܂B

  ̌A

  ! Now we want to move to protected mode ...

      [悢veNg[hֈڍs鎞AAA]

  ! we get the code32 start address and modify the below 'jmpi'
  ! (loader may have changed it)

      [code32 ̊JnAhX擾ĉ "jmpi" ύX
      ([_[ɂĕύXĂ邩Ȃ̂)]

  ! Now we move the system to its rightful place
  ! ...but we check, if we have a big-kernel.
  ! in this case we *must* not move it ...

      [AVXe𐳋K̏ꏊֈړ悤AAȂO
      big-kernel gĂ邩ǂ`FbNȂƃ_B
       big-kernel gĂȂAꏊړ *Ă͂ȂȂ* ]

  ! then we load the segment descriptors

      [ɃZOgfXNv^ (AhX) [h]

  ! If we have our code not at 0x90000, we need to move it there now.
  ! We also then need to move the parameters behind it (command line)
  ! Because we would overwrite the code on the current IP, we move
  ! it in two steps, jumping high after the first one.

      [J[lR[h 0x90000 ɖA̎_łֈړ
      KvB܂Ǎ̃p[^ (R}hCp[^) 
      킹ĈړȂ΂ȂȂB
      ݂̓͌ IP ɂR[h㏑Ă܂߁Aړ
      2 iKɕčsBŏ̈ړ̌ high ̈ֈڍŝB]

  ! that was painless, now we enable A20

      [͂ƂȂBAA20 Lɂ悤B]

  ! wait until a20 really *is* enabled; it can take a fair amount of
  ! time on certain systems; Toshiba Tecras are known to have this
  ! problem.  The memory location used here is the int 0x1f vector,
  ! which should be safe to use; any *unused* memory location < 0xfff0
  ! should work here.

      [a20 u{ɁvLɂȂ܂ő҂ƂB̃VXeł͂̂߂
      炭ԂKvȂ񂾁B Toshiba  Tecra V[Y̖͂
      Ă邱ƂŒmĂBŎgĂ郁[̈ʒu
      xN^[ int 0x1f ŁAgĂvȂ͂B̎_ł 0xfff0 
      ̎gĂȂ[ʒuȂǂłpł͂Ȃ񂾁B]

  ƁA32bit protect mode ւ̈ڍs̏i߂Ă܂B

  Ō "wait until a20 really ..."  2.0.xx nJ[l bzImage ɂ
  ƋNłȂł TECRA  Portege Ȃǂn߂Ƃm[g PC
  Ȃǂւ̑΍łˁB 2.2 nJ[lł TECRA Ȃǂ̃m[g PC łS
   bzImage 𗘗pł悤ɂȂ炵Ƃb𕷂Ƃ
  ܂B

  āAC^vg֌W̏B

  ! make sure any possible coprocessor is properly reset..

      [ڑĂ\̂邷ׂẴRvZbTƃZbg
      邱ƂmF悤AAA]

  ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
  ! we put them right after the intel-reserved hardware interrupts, at
  ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
  ! messed this up with the original PC, and they haven't been able to
  ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
  ! which is used for the internal hardware interrupts as well. We just
  ! have to reprogram the 8259's, and it isn't fun.

      [A܂ł͂Ԃ񂤂܂BvBāAꂩ
      荞݂Đݒ (reprogram) ȂႢȂB(EU)

      Linux ł͊荞݂ Intel \񂵂n[hEFA荞݂̂A
      int 0x20-0x2F ɉނ񂾁BȂ牽זȂˁB
      ߂ƂɁAIBM ͍ŏ PC ہA荞݂̐ݒ`N`
      Ă܂BāAǔނ͂𒼂ƂłȂ񂾁B
      ABIOS ̊荞݂̓n[hEFA̓荞݂gĂ̂
      ̈A0x08-0x0f ɂ񂾂BƂ킯ŁAl͂ꂩ 8259 
      vOȂƂȂBĂ͑SRyȂ񂾁B]

  ! Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
  ! need no steenking BIOS anyway (except for the initial loading :-).
  ! The BIOS routine wants lots of unnecessary data, and it's less
  ! "interesting" anyway. This is how REAL programmers do it.

      [[A͂ɂƂʔȂ (ꂽ)B
      ƂɂAł܂ĂƎvBɁAǂɂĂ
       BIOS Kv͖񂾁B(ŏ̃[hȊÓB킩)
      BIOS [`͂₽Ƃ̕svȃf[^~邵A
      SR "낢" ƂȂBu{́vvO}Ȃ炱邳B]

  ! Well, now's the time to actually move into protected mode. To make
  ! things as simple as possible, we do no register set-up or anything,
  ! we let the GNU-compiled 32-bit programs do that. We just jump to
  ! absolute address 0x1000 (or the loader supplied one),
  ! in 32-bit protected mode.

      [āAx{ɃveNg[hֈڍs鎞Bł邾
      Pɕۂ߂ɁAWX^[ݒƂ͉̂ȂB
      ł GNU ̃c[ŃRpCꂽ 32-bit ̃vOɂ
      点񂾁BP 32-bit ̃veNg[hŐ΃AhX 0x1000
      ([_[w肵ꏊ) փWv邾B]

  ! Note that the short jump isn't strictly needed, although there are
  ! reasons why it might be a good idea. It won't hurt in any case.

      [ short jump ǂĂKvĂ킯ȂƂɒӁB
      AĂقR񂾁B
      ĉ肪NĂƂȂˁB]

  ǂ Linus ͍ŏɊJn߂Â̏ɑJ
  炵A"Sadly IBM messed this up" Ƃ "and it isn't fun." ܂
  "Well, that certainly wasn't fan :-(."  ȂĂ̂܂BŁA
  ̋ʂɂ͂ȂɈĂ悤ŁA"This is how REAL
  programmers do it."  ȂǂƏĂ܂B

  JF <http://www.linux.or.jp/JF/> ̎ "Linux HISTORY" Ƃ
  ܂A̒ɂȈ߂܂B

       > 1) J[lĂƂɂ́Aǂăfob
       O܂ ?

       gĂ}VƁAƂ̐i݋ɂ܂BƃVv
       ȃVXeȂ炽ĂZbgAbv͂ƊȒPłBveN
       g[h 386 ŎȂ΂ȂȂƂ
       B

       Ԗȏ͈ԍŏłBprintf gŒ̃VXe
       ɓ邱ƂłłĂA386 ł̃veN
       g[hւ̈ڍs͊yȂłB 386 ̃A[LeN`
       mʂ܂܂Ɏn߂̂ł΂ȂłB̒iKł́AV
       Xe͎ɂȂقǃu[g܂܂B 386 
       ɂwƋCÂɂ́AVbg_Eău[g
       ܂܂B̂̏؋cɂ܂B

       printf() Ėɗ܂Bu[gΉʂ
       ςłBꂩAVRAM @Ȃ΂߂łB VRAM
       ̓ZOgԈĂ肷ƗĂ܂Bfob
       KȂčl邾ʂłB386 ̃veNg[h܂ł
       fobKȂĕƂ܂B386 G~[^
       Aꕔ̏d̃}VȂȂƂȂ邩܂񂪁A
       ͑ʖڂłB

       ĝ́A̎ԉ҂̃[vłB

         die:
                  jmp die

       ̂悤Ȃ̂ƂƂɓ܂B~܂Ă܂
        OK łAu[gĂ܂AȂƂ die
       [v̑OƂ킩܂BςɃTEh|[gp
       ł܂A PC ̃n[h͂ƂȂ̂ŁAS
       Rg܂łBȊOɕ@Ȃ킯ł͂܂B
       ̓J[lƎvĎn߂̂ł͂ȂA 386 ̃^
       XNXCb`ɂĒm肽łBAƂɂ
       ďn߂܂B (91N4̂Ƃł)

       Œ̃VXeoオAXN[o͂Ɏg悤
       ȂƁAXyɂȂ܂BAŊ荞݂Lɂ
       ΂Ȃ܂BhJ`BȂ胊u[gāA܂ŏ
       @ɋt߂BSĂ̒qŁA悻 2āA386 ̂
       ܂Ƃɓ悤ɂ܂Bꂩ́Au[gȂ
       悤ɂƋCgȂAɊ{IȂ (y[WOA^C
       }荞݁APȃ^XNXCb`AZOg̃eXg) 
       ƂƂȂōςނ悤ɂȂ܂B

  ̘̂bǂނƁAsetup.S ̃C^vg֌W̏veNg
  [hւ̈ڍsɊւ鏈ɂRg̔wiƂȂ킩悤ȋC
  Ă܂ ?
  ȂAsetup.S ͍̏ŌɃJ[l{̂̃AhXփWvďI
  ܂B

  ! NOTE: For high loaded big kernels we need a
  !       jmpi    0x100000,__KERNEL_CS

            [: high ̈Ƀ[hꂽ big J[l̏ꍇA
             "jmpi    0x100000,__KERNEL_CS" sKvB]

  !       but we yet haven't reloaded the CS register, so the default size
  !       of the target offset still is 16 bit.
  !       However, using an operant prefix (0x66), the CPU will properly
  !       take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
  !       Manual, Mixing 16-bit and 32-bit code, page 16-6)

            [ł̎_ł͂܂ CS WX^[ă[hĂȂA
            ^[QbgItZbg̃ftHgTCY͂܂ 16 bit Ȃ񂾁B
            Ƃ낪AIygvtBbNX (0x66) g΁ACPU 
            ܂ 48 bit  far |C^ĂB
            (INTeL 80386 vO}[Yt@X}jAA
             16-bit  32-bit ̃R[h̍pAy[W 16-6)]

          db      0x66,0xea       ! prefix + jmpi-opcode
  code32: dd      0x1000          ! will be set to 0x100000 for big kernels
          dw      __KERNEL_CS

  5.  J[l{̂̓WJ

   arch/i386/boot/setup.S 珈puJ[l{́vł
  A͂܂̎v͈kꂽԂŃ[ɒuĂ܂B

  ۂɃJ[ln߂OɁA܂̈kꂽJ[l𕜌
  ΂܂B

  ́Aarch/i386/boot/compressed/head.S ɂ

  /*
   * Do the decompression, and jump to the new kernel..
   */
          subl $16,%esp   # place for structure on the stack
          pushl %esp      # address of structure as first arg
          call SYMBOL_NAME(decompress_kernel)
          orl  %eax,%eax
          jnz  3f
          xorl %ebx,%ebx
          ljmp $(__KERNEL_CS), $0x100000

  ɂĎs܂BȂ decompress_kernel ͓fBNg
   arch/i386/boot/compress/misc.c ̒

  int decompress_kernel(struct moveparams *mv)
  {
          if (SCREEN_INFO.orig_video_mode == 7) {
                  vidmem = (char *) 0xb0000;
                  vidport = 0x3b4;
          } else {
                  vidmem = (char *) 0xb8000;
                  vidport = 0x3d4;
          }

          lines = SCREEN_INFO.orig_video_lines;
          cols = SCREEN_INFO.orig_video_cols;

          if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
          else setup_output_buffer_if_we_run_high(mv);

          makecrc();
          puts("Uncompressing Linux... ");
          gunzip();
          puts("Ok, booting the kernel.\n");
          if (high_loaded) close_output_buffer_if_we_run_high(mv);
          return high_loaded;
  }

  ƂĒ`ĂAɂ̒ŎgĂ gunzip() ɂĂ
  lib/infalte.c ̒Œ`Ă܂B

  (ŋN "Uncompressing Linux... " ƂbZ[WoĂ
  ̂A킩܂ˁB)

  āAarch/i386/boot/compressed/head.S ̖`ɏĂRg
  ȉɈpĂ݂܂傤B

  /*
   *  linux/boot/head.S
   *
   *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
   */

  /*
   *  head.S contains the 32-bit startup code.
   *

   ? t@CႢ܂ˁB Linux J[l݂̂悤ɑ
  ̋@ɈڐAĂȂ 1.x ̍ȑÕt@Cł傤B
  ݂̂悤ɃA[LeN`ɈˑĂ܂ł
  B

  āAkĂJ[l{̂WJ܂B͂̒ɃWv
  Ă܂Barch/i386/boot/compressed/head.S ̍Ō͎̂悤ɂȂ
  Ă܂B

  /*
   * Do the decompression, and jump to the new kernel..
   */
          subl $16,%esp   # place for structure on the stack
          pushl %esp      # address of structure as first arg
          call SYMBOL_NAME(decompress_kernel)
          orl  %eax,%eax
          jnz  3f
          xorl %ebx,%ebx
          ljmp $(__KERNEL_CS), $0x100000

  /*
   * We come here, if we were loaded high.
   * We need to move the move-in-place routine down to 0x1000
   * and then start it with the buffer addresses in registers,
   * which we got from the stack.
   */
  3:
          movl $move_routine_start,%esi
          movl $0x1000,%edi
          movl $move_routine_end,%ecx
          subl %esi,%ecx
          cld
          rep
          movsb

          popl %esi       # discard the address
          popl %esi       # low_buffer_start
          popl %ecx       # lcount
          popl %edx       # high_buffer_start
          popl %eax       # hcount
          movl $0x100000,%edi
          cli             # make sure we don't get interrupted
          ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine

  /*
   * Routine (template) for moving the decompressed kernel in place,
   * if we were high loaded. This _must_ PIC-code !
   */
  move_routine_start:
          rep
          movsb
          movl %edx,%esi
          movl %eax,%ecx  # NOTE: rep movsb won't move if %ecx == 0
          rep
          movsb
          xorl %ebx,%ebx
  /*
   * Well, the kernel relies on %esp pointing into low mem,
   * with the decompressor loaded high this is no longer true,
   * so we set esp here.
   */
          mov  $0x90000,%esp
          ljmp $(__KERNEL_CS), $0x100000
  move_routine_end:

  "decompress_kernel" ̂ "jnz"  "3:"փWvɁÂ
  "ljmp $(__KERNEL_CS), $0x100000" ꍇ (zImage) ƁA "3:"
  փWv "move_routine_start:"  "move_routine_end:" ̊ԂœWJ
  J[l̏ꏊ̈ړsȂĂ "ljmp $(__KERNEL_CS),
  $0x100000" ꍇ (bzImage) ܂B

  6.  foCXhCo[̐ݒ

  āAWJꂽJ[l{̂ōŏɎŝ́A
  arch/i386/kernel/head.S łBɂĖ`̃RgB

  /*
   *  linux/arch/i386/head.S -- the 32-bit startup code.
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   *
   *  Enhanced CPU detection and feature setting code by Mike Jagdis
   *  and Martin Mares, November 1997.
   */

  u32bit X^[gAbvvuꂽ CPU oƋ@\ݒvƂ
  ł܂B

  RgǂĂ݂܂傤B

   * References to members of the boot_cpu_data structure.

   * swapper_pg_dir is the main page directory, address 0x00101000

   * Set segments to known values

   *      New page tables may be in 4Mbyte page mode and may
   *      be using the global pages.
   *
   *      NOTE! We have to correct for the fact that we're
   *      not yet offset PAGE_OFFSET..

   * Setup paging (the tables are already set up, just switch them on)

   * Clear BSS first so that there are no surprises...

   * start system 32-bit setup. We need to re-do some of the things done
   * in 16-bit mode for the "real" operations.

   * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
   * confuse the debugger if this code is traced.
   * XXX - best to initialize before switching to protected mode.

   * Copy bootup parameters out of the way. First 2kB of
   * _empty_zero_page is for boot parameters, second 2kB
   * is for the command line.

  /* check if it is 486 or 386. */

   * XXX - this does a lot of unnecessary setup.  Alignment checks don't
   * apply at our cpl of 0 and the stack ought to be aligned already, and
   * we don't need to preserve eflags.

  ǂA[Ǘe[u CPU ̃tbOݒȂǂsȂĂ
  悤łB

   head.S ͍Ō start_kernel s܂B

          xorl %eax,%eax
          lldt %ax
          cld                     # gcc2 wants the direction flag cleared at all times
          call SYMBOL_NAME(start_kernel)
  L6:
          jmp L6                  # main should never return here, but
                                  # just in case, we know what happens.

  head.S Ăяo start_kernel  init/main.c ɂ܂B
  t@C̖`ɂRgp܂B

  /*
   *  linux/init/main.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   *
   *  GK 2/5/95  -  Changed to support mounting root fs via NFS
   *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
   *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
   *  Simplified starting of init:  Michael A. Griffith <grif@acm.org>
   */

  āAstart_kernel ̍ŏ̕łB

  asmlinkage void __init start_kernel(void)
  {
          char * command_line;

  #ifdef __SMP__
          static int boot_cpu = 1;
          /* "current" has been set up, we need to load it now */
          if (!boot_cpu)
                  initialize_secondary();
          boot_cpu = 0;
  #endif

  /*
   * Interrupts are still disabled. Do necessary setups, then
   * enable them
   */
          printk(linux_banner);
          setup_arch(&command_line, &memory_start, &memory_end);
          memory_start = paging_init(memory_start,memory_end);
          trap_init();
          init_IRQ();
          sched_init();
          time_init();
          parse_options(command_line);

  "linux_banner" Ƃ̂ init/version.c ɒ`܂BႦ (
  ͎gĂ 2.0.36 ̗ł)

  Linux version 2.0.36 (root@pika) (gcc version 2.7.2.3) #1 Wed Feb 10 21:57:36 JST 1999

  Ƃ̂̂łBNɂ́uoi[voĂ̂
  init/main.c  start_kernel 킯łˁB

   "setup_arch" łA arch/i386/kernel/setup.c Œ`
  ܂Be͎Ԃ̓sŏȗ܂AN BIOS W
   (̃foCXhCo[ANZXł悤) 炽߂ĐĂ
  ܂B"paging_init"  arch/i386/mm/setup.c ɂ܂B[y[W
  e[u̐ݒsȂ܂B "trap_init"  arch/i386/kernel/traps.c
  ɂ IDT e[ȕs܂B"init_IRQ" 
  arch/i386/kernel/irq.c ̒ɂ܂BIRQ ֌W̐ݒsȂ̂
  B"shced_init"  kernel/sched.c ̒Œ`Ă܂B
  "time_init"  kernel/time.c ɁA parse_optinos  start_kernel
  Ɠ init/main.c ̒Œ`Ă܂B

  ̂ƁA[`s

          kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);

  ɓB܂BňƂĎw肳Ă "init" ͓ init/main.c
  ̒Œ`Ă̂łB

  static int init(void * unused)
  {
          lock_kernel();
          do_basic_setup();

          /*
           * Ok, we have completed the initial bootup, and
           * we're essentially up and running. Get rid of the
           * initmem segments and start the user-mode stuff..
           */
          free_initmem();
          unlock_kernel();

          if (open("/dev/console", O_RDWR, 0) < 0)
                  printk("Warning: unable to open an initial console.\n");

          (void) dup(0);
          (void) dup(0);

   "init" ̒ŌĂяoĂ lock_kernel  SMP ̋@Bɂ̂݊֌W
  ̂łB

   do_basic_setup  init/main.c ̒Œ`Ă܂B̊֐
  ɂ̓oX̐ݒlbg[N\Pbg̏At@CVXe̔F
  A[gp[eBṼ}EgȂǁufoCXhCȍvƂ
  ^Cgɂӂ킵e܂܂Ă̂ŁA{Ȃ炱̒gꂼ
  ꒲ׂĂ݂ƂȂ̂łA͎ԂȂĂ܂̂ŏȗ
  ܂B

  ΁A񎩕ŒׂĂ݂ĉB

  7.  init ̋N

  ̍ڂňꕔЉ init/main.c Œ`ĂAJ[l
  "init" ֐łAŌ͂ȕɂȂĂ܂B

          /*
           * We try each of these until one succeeds.
           *
           * The Bourne shell can be used instead of init if we are
           * trying to recover a really broken machine.
           */

          if (execute_command)
                  execve(execute_command,argv_init,envp_init);
          execve("/sbin/init",argv_init,envp_init);
          execve("/etc/init",argv_init,envp_init);
          execve("/bin/init",argv_init,envp_init);
          execve("/bin/sh",argv_init,envp_init);
          panic("No init found.  Try passing init= option to kernel.");

   if (execute_command) n܂ 2 śAÑJ[lIv
  V init= ɂčŏɋNvOw肵ꍇ̂߂̂
  ̂łBIvVw肵Ȃꍇ͂̂܂ܒʉ߂܂B

   execve("/sbin/init",...)  /sbin/init sāA肪
  ΂̂܂ܖ߂ĂȂAƂ߂łBʏ̃VXeNł͂
  䂪 /sbin/init ɈڍsāAȌ̃R[h͎g܂B

  炩̗R /sbin/init słȂꍇ́Al̕@
  /etc/initA/bin/initA /bin/sh ̎s܂BɎ
  ̂܂sł΁Â܂܏nĂ܂̂łȍ~̃R[
  h͎s܂B

  ŏIIɁA/bin/sh ܂߂āAǂĂnƂłȂꍇ́A
  Ō panic() ŃG[bZ[W\Ē~܂B

  ܂A "man 8 init" ɋLڂĂuJ[lu[g̍Ō̃X
  ebvvƂ킯łB

  8.  ԊO: Makefile ɂ

  J[l[hꂽɁAǂ̃t@CɓĂR[hs
  ̂AƂ_ Makefile 𒲂ׂƏĂ܂B

  ܂gbvfBNg Makefile ɂ́A̋Lq܂B

  include arch/$(ARCH)/Makefile

  vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
          $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
                  --start-group \
                  $(CORE_FILES) \
                  $(FILESYSTEMS) \
                  $(NETWORKS) \
                  $(DRIVERS) \
                  $(LIBS) \
                  --end-group \
                  -o vmlinux
          $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map

  ̘bł i386 OƂĂ̂ "arch/i386/Makefile" QƂ
  ݂ƁA

  HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o

  zImage: vmlinux
          @$(MAKEBOOT) zImage

  ƂLq܂BƏL̃gbvfBNg Makefile 
  AgbvfBNg vmlinux ̐擪 "arch/i386/kernel/head.o"
  ł邱Ƃ킩܂BAgbvfBNg Makefile ɂ́A
  Lq܂B

  boot: vmlinux
          @$(MAKE) -C arch/$(ARCH)/boot

  ̋LqAu[gC[W̍쐬ɂĒm肽΁A
  "arch/i386/boot" fBNg Makefile 𒲂ׂĂ݂ƗǂA
  Ƃ킩܂B

   "arch/i386/boot" fBNg Makefile Ă݂ƁA̋Lq
  ܂B

  zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
          $(OBJCOPY) compressed/vmlinux compressed/vmlinux.out
          tools/build bootsect setup compressed/vmlinux.out $(ROOT_DEV) > zImage

  compressed/vmlinux: $(TOPDIR)/vmlinux
          @$(MAKE) -C compressed vmlinux

  setup: setup.o
          $(LD86) -s -o $@ $<

  setup.o: setup.s
          $(AS86) -o $@ $<

  setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h
          $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@

  bootsect: bootsect.o
          $(LD86) -s -o $@ $<

  bootsect.o: bootsect.s
          $(AS86) -o $@ $<

  bootsect.s: bootsect.S Makefile $(BOOT_INCL)
          $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@

  Abootsect.S  bootsect.s 쐬A bootsect.o 
  oR bootsect ɂȂ邱ƁA setup.S  vide.S  setup.s 
  쐬A setup.o oR setup ɂȂ邱Ƃ킩܂B܂
  Ăł bootsect  setup ꂼ zImage t@C̐擪 2
  ԖڂɊY邱Ƃ킩܂B(]āAtbs[J[lu[
  gƍŏ bootsect.S ̃R[hs킯ł)

  ĂɁAarch/i386/boot/compressed/Makefile ƈȉ̋Lq
  ܂B

  HEAD = head.o
  SYSTEM = $(TOPDIR)/vmlinux

  OBJECTS = $(HEAD) misc.o

  vmlinux: piggy.o $(OBJECTS)
          $(LD) $(ZLINKFLAGS) -o vmlinux $(OBJECTS) piggy.o

  head.o: head.S $(TOPDIR)/include/linux/tasks.h
          $(CC) $(AFLAGS) -traditional -c head.S

  piggy.o:        $(SYSTEM)
          tmppiggy=_tmp_$$$$piggy; \
          rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \
          $(OBJCOPY) $(SYSTEM) $$tmppiggy; \
          gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
          echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
          $(LD) -m elf_i386 -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-i386 -T $$tmppiggy.lnk; \
          rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk

  ꂩAcompressed/vmlinux ̐擪 head.S ̃R[hł邱Ƃ킩
  ܂B

  ȏ̂Ƃ܂Ƃ߂

  1. arch/i386/boot/bootsect.S (tbs[u[gAŏɎs)

  2. arch/i386/boot/setup.S (+ video.S)

  3. arch/i386/boot/compressed/head.S (+ misc.c)

  4. arch/i386/kernel/head.S

  ƂƂɂȂ܂B

  9.  I

  9.1.  肢

  Ƃ肠ȂƂ܂Ƃ߂Ă݂܂AȂɂԂA܂܂mȂ
  Ƃ񂠂܂BɏɂԈႢ邩܂B
  ǂ̂߂̃AhoCXłA񋳂ĂB낵
  肢܂B

  9.2.  ӎ

  ŏɂ̕[X܂łɁANLUG  JF ̃o[̕X瑽
  ̗LvȈӌ𒸂܂B肪Ƃ܂B܂Ab
  ȂĂ fj.os.linux  Nifty FUNIX ̕Xɂ̏؂Ă\
  グ܂B

  ŏɃ[XŁA񂩂 BIOS ɂu[gXgbv̓
  ɂČwE𒸂܂B܂肱񂩂 "the longest-living
  linux bug" ̐ɂėLvȌӌ𒸂܂Bǂ肪Ƃ
  ܂B

  {񂩂 i386 ̃AZuɂĎQlɂȂ𒸂܂Bǂ
  肪Ƃ܂B

  9.3.  ̔̕zzɂ

   copyrighted (c) 1999 Taketoshi Sano

  ̕ GNU pubNCZX (GPL) o[W 2 ȍ~̏
  A邢͕WI Linux hLgvWFNg (LDP) ̏Ɋ
  zzȂΎRɂĂĂ܂܂B̃CZX͂
  ̃hLgł悤ȃTCgł܂BLDP ̏
  (|̂) ȂCĂ܂BCꂽo[W
  GPL ̊ł̂ݔzẑƂ邱Ƃ\łB

