Advertisement
Guest User

Untitled

a guest
Aug 7th, 2017
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 248.59 KB | None | 0 0
  1. Makefile
  2.  
  3. #
  4. # Makefile for linux.
  5. # If you don't have '-mstring-insns' in your gcc (and nobody but me has :-)
  6. # remove them from the CFLAGS defines.
  7. #
  8.  
  9. AS86 =as -0 -a
  10. CC86 =cc -0
  11. LD86 =ld -0
  12.  
  13. AS =gas
  14. LD =gld
  15. LDFLAGS =-s -x -M
  16. CC =gcc
  17. CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs
  18. CPP =gcc -E -nostdinc -Iinclude
  19.  
  20. ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
  21. LIBS =lib/lib.a
  22.  
  23. .c.s:
  24. $(CC) $(CFLAGS) \
  25. -nostdinc -Iinclude -S -o $*.s $<
  26. .s.o:
  27. $(AS) -c -o $*.o $<
  28. .c.o:
  29. $(CC) $(CFLAGS) \
  30. -nostdinc -Iinclude -c -o $*.o $<
  31.  
  32. all: Image
  33.  
  34. Image: boot/boot tools/system tools/build
  35. tools/build boot/boot tools/system > Image
  36. sync
  37.  
  38. tools/build: tools/build.c
  39. $(CC) $(CFLAGS) \
  40. -o tools/build tools/build.c
  41. chmem +65000 tools/build
  42.  
  43. boot/head.o: boot/head.s
  44.  
  45. tools/system: boot/head.o init/main.o \
  46. $(ARCHIVES) $(LIBS)
  47. $(LD) $(LDFLAGS) boot/head.o init/main.o \
  48. $(ARCHIVES) \
  49. $(LIBS) \
  50. -o tools/system > System.map
  51.  
  52. kernel/kernel.o:
  53. (cd kernel; make)
  54.  
  55. mm/mm.o:
  56. (cd mm; make)
  57.  
  58. fs/fs.o:
  59. (cd fs; make)
  60.  
  61. lib/lib.a:
  62. (cd lib; make)
  63.  
  64. boot/boot: boot/boot.s tools/system
  65. (echo -n "SYSSIZE = (";ls -l tools/system | grep system \
  66. | cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
  67. cat boot/boot.s >> tmp.s
  68. $(AS86) -o boot/boot.o tmp.s
  69. rm -f tmp.s
  70. $(LD86) -s -o boot/boot boot/boot.o
  71.  
  72. clean:
  73. rm -f Image System.map tmp_make boot/boot core
  74. rm -f init/*.o boot/*.o tools/system tools/build
  75. (cd mm;make clean)
  76. (cd fs;make clean)
  77. (cd kernel;make clean)
  78. (cd lib;make clean)
  79.  
  80. backup: clean
  81. (cd .. ; tar cf - linux | compress16 - > backup.Z)
  82. sync
  83.  
  84. dep:
  85. sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
  86. (for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done) >> tmp_make
  87. cp tmp_make Makefile
  88. (cd fs; make dep)
  89. (cd kernel; make dep)
  90. (cd mm; make dep)
  91.  
  92. ### Dependencies:
  93. init/main.o : init/main.c include/unistd.h include/sys/stat.h \
  94. include/sys/types.h include/sys/times.h include/sys/utsname.h \
  95. include/utime.h include/time.h include/linux/tty.h include/termios.h \
  96. include/linux/sched.h include/linux/head.h include/linux/fs.h \
  97. include/linux/mm.h include/asm/system.h include/asm/io.h include/stddef.h \
  98. include/stdarg.h include/fcntl.h
  99.  
  100. ------------------------------------------------------------------------
  101.  
  102. boot/boot.s
  103.  
  104. |
  105. | boot.s
  106. |
  107. | boot.s is loaded at 0x7c00 by the bios-startup routines, and moves itself
  108. | out of the way to address 0x90000, and jumps there.
  109. |
  110. | It then loads the system at 0x10000, using BIOS interrupts. Thereafter
  111. | it disables all interrupts, moves the system down to 0x0000, changes
  112. | to protected mode, and calls the start of system. System then must
  113. | RE-initialize the protected mode in it's own tables, and enable
  114. | interrupts as needed.
  115. |
  116. | NOTE! currently system is at most 8*65536 bytes long. This should be no
  117. | problem, even in the future. I want to keep it simple. This 512 kB
  118. | kernel size should be enough - in fact more would mean we'd have to move
  119. | not just these start-up routines, but also do something about the cache-
  120. | memory (block IO devices). The area left over in the lower 640 kB is meant
  121. | for these. No other memory is assumed to be "physical", ie all memory
  122. | over 1Mb is demand-paging. All addresses under 1Mb are guaranteed to match
  123. | their physical addresses.
  124. |
  125. | NOTE1 abouve is no longer valid in it's entirety. cache-memory is allocated
  126. | above the 1Mb mark as well as below. Otherwise it is mainly correct.
  127. |
  128. | NOTE 2! The boot disk type must be set at compile-time, by setting
  129. | the following equ. Having the boot-up procedure hunt for the right
  130. | disk type is severe brain-damage.
  131. | The loader has been made as simple as possible (had to, to get it
  132. | in 512 bytes with the code to move to protected mode), and continuos
  133. | read errors will result in a unbreakable loop. Reboot by hand. It
  134. | loads pretty fast by getting whole sectors at a time whenever possible.
  135.  
  136. | 1.44Mb disks:
  137. sectors = 18
  138. | 1.2Mb disks:
  139. | sectors = 15
  140. | 720kB disks:
  141. | sectors = 9
  142.  
  143. .globl begtext, begdata, begbss, endtext, enddata, endbss
  144. .text
  145. begtext:
  146. .data
  147. begdata:
  148. .bss
  149. begbss:
  150. .text
  151.  
  152. BOOTSEG = 0x07c0
  153. INITSEG = 0x9000
  154. SYSSEG = 0x1000 | system loaded at 0x10000 (65536).
  155. ENDSEG = SYSSEG + SYSSIZE
  156.  
  157. entry start
  158. start:
  159. mov ax,#BOOTSEG
  160. mov ds,ax
  161. mov ax,#INITSEG
  162. mov es,ax
  163. mov cx,#256
  164. sub si,si
  165. sub di,di
  166. rep
  167. movw
  168. jmpi go,INITSEG
  169. go: mov ax,cs
  170. mov ds,ax
  171. mov es,ax
  172. mov ss,ax
  173. mov sp,#0x400 | arbitrary value >>512
  174.  
  175. mov ah,#0x03 | read cursor pos
  176. xor bh,bh
  177. int 0x10
  178.  
  179. mov cx,#24
  180. mov bx,#0x0007 | page 0, attribute 7 (normal)
  181. mov bp,#msg1
  182. mov ax,#0x1301 | write string, move cursor
  183. int 0x10
  184.  
  185. | ok, we've written the message, now
  186. | we want to load the system (at 0x10000)
  187.  
  188. mov ax,#SYSSEG
  189. mov es,ax | segment of 0x010000
  190. call read_it
  191. call kill_motor
  192.  
  193. | if the read went well we get current cursor position ans save it for
  194. | posterity.
  195.  
  196. mov ah,#0x03 | read cursor pos
  197. xor bh,bh
  198. int 0x10 | save it in known place, con_init fetches
  199. mov [510],dx | it from 0x90510.
  200.  
  201. | now we want to move to protected mode ...
  202.  
  203. cli | no interrupts allowed !
  204.  
  205. | first we move the system to it's rightful place
  206.  
  207. mov ax,#0x0000
  208. cld | 'direction'=0, movs moves forward
  209. do_move:
  210. mov es,ax | destination segment
  211. add ax,#0x1000
  212. cmp ax,#0x9000
  213. jz end_move
  214. mov ds,ax | source segment
  215. sub di,di
  216. sub si,si
  217. mov cx,#0x8000
  218. rep
  219. movsw
  220. j do_move
  221.  
  222. | then we load the segment descriptors
  223.  
  224. end_move:
  225.  
  226. mov ax,cs | right, forgot this at first. didn't work :-)
  227. mov ds,ax
  228. lidt idt_48 | load idt with 0,0
  229. lgdt gdt_48 | load gdt with whatever appropriate
  230.  
  231. | that was painless, now we enable A20
  232.  
  233. call empty_8042
  234. mov al,#0xD1 | command write
  235. out #0x64,al
  236. call empty_8042
  237. mov al,#0xDF | A20 on
  238. out #0x60,al
  239. call empty_8042
  240.  
  241. | well, that went ok, I hope. Now we have to reprogram the interrupts :-(
  242. | we put them right after the intel-reserved hardware interrupts, at
  243. | int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
  244. | messed this up with the original PC, and they haven't been able to
  245. | rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
  246. | which is used for the internal hardware interrupts as well. We just
  247. | have to reprogram the 8259's, and it isn't fun.
  248.  
  249. mov al,#0x11 | initialization sequence
  250. out #0x20,al | send it to 8259A-1
  251. .word 0x00eb,0x00eb | jmp $+2, jmp $+2
  252. out #0xA0,al | and to 8259A-2
  253. .word 0x00eb,0x00eb
  254. mov al,#0x20 | start of hardware int's (0x20)
  255. out #0x21,al
  256. .word 0x00eb,0x00eb
  257. mov al,#0x28 | start of hardware int's 2 (0x28)
  258. out #0xA1,al
  259. .word 0x00eb,0x00eb
  260. mov al,#0x04 | 8259-1 is master
  261. out #0x21,al
  262. .word 0x00eb,0x00eb
  263. mov al,#0x02 | 8259-2 is slave
  264. out #0xA1,al
  265. .word 0x00eb,0x00eb
  266. mov al,#0x01 | 8086 mode for both
  267. out #0x21,al
  268. .word 0x00eb,0x00eb
  269. out #0xA1,al
  270. .word 0x00eb,0x00eb
  271. mov al,#0xFF | mask off all interrupts for now
  272. out #0x21,al
  273. .word 0x00eb,0x00eb
  274. out #0xA1,al
  275.  
  276. | well, that certainly wasn't fun :-(. Hopefully it works, and we don't
  277. | need no steenking BIOS anyway (except for the initial loading :-).
  278. | The BIOS-routine wants lots of unnecessary data, and it's less
  279. | "interesting" anyway. This is how REAL programmers do it.
  280. |
  281. | Well, now's the time to actually move into protected mode. To make
  282. | things as simple as possible, we do no register set-up or anything,
  283. | we let the gnu-compiled 32-bit programs do that. We just jump to
  284. | absolute address 0x00000, in 32-bit protected mode.
  285.  
  286. mov ax,#0x0001 | protected mode (PE) bit
  287. lmsw ax | This is it!
  288. jmpi 0,8 | jmp offset 0 of segment 8 (cs)
  289.  
  290. | This routine checks that the keyboard command queue is empty
  291. | No timeout is used - if this hangs there is something wrong with
  292. | the machine, and we probably couldn't proceed anyway.
  293. empty_8042:
  294. .word 0x00eb,0x00eb
  295. in al,#0x64 | 8042 status port
  296. test al,#2 | is input buffer full?
  297. jnz empty_8042 | yes - loop
  298. ret
  299.  
  300. | This routine loads the system at address 0x10000, making sure
  301. | no 64kB boundaries are crossed. We try to load it as fast as
  302. | possible, loading whole tracks whenever we can.
  303. |
  304. | in: es - starting address segment (normally 0x1000)
  305. |
  306. | This routine has to be recompiled to fit another drive type,
  307. | just change the "sectors" variable at the start of the file
  308. | (originally 18, for a 1.44Mb drive)
  309. |
  310. sread: .word 1 | sectors read of current track
  311. head: .word 0 | current head
  312. track: .word 0 | current track
  313. read_it:
  314. mov ax,es
  315. test ax,#0x0fff
  316. die: jne die | es must be at 64kB boundary
  317. xor bx,bx | bx is starting address within segment
  318. rp_read:
  319. mov ax,es
  320. cmp ax,#ENDSEG | have we loaded all yet?
  321. jb ok1_read
  322. ret
  323. ok1_read:
  324. mov ax,#sectors
  325. sub ax,sread
  326. mov cx,ax
  327. shl cx,#9
  328. add cx,bx
  329. jnc ok2_read
  330. je ok2_read
  331. xor ax,ax
  332. sub ax,bx
  333. shr ax,#9
  334. ok2_read:
  335. call read_track
  336. mov cx,ax
  337. add ax,sread
  338. cmp ax,#sectors
  339. jne ok3_read
  340. mov ax,#1
  341. sub ax,head
  342. jne ok4_read
  343. inc track
  344. ok4_read:
  345. mov head,ax
  346. xor ax,ax
  347. ok3_read:
  348. mov sread,ax
  349. shl cx,#9
  350. add bx,cx
  351. jnc rp_read
  352. mov ax,es
  353. add ax,#0x1000
  354. mov es,ax
  355. xor bx,bx
  356. jmp rp_read
  357.  
  358. read_track:
  359. push ax
  360. push bx
  361. push cx
  362. push dx
  363. mov dx,track
  364. mov cx,sread
  365. inc cx
  366. mov ch,dl
  367. mov dx,head
  368. mov dh,dl
  369. mov dl,#0
  370. and dx,#0x0100
  371. mov ah,#2
  372. int 0x13
  373. jc bad_rt
  374. pop dx
  375. pop cx
  376. pop bx
  377. pop ax
  378. ret
  379. bad_rt: mov ax,#0
  380. mov dx,#0
  381. int 0x13
  382. pop dx
  383. pop cx
  384. pop bx
  385. pop ax
  386. jmp read_track
  387.  
  388. /*
  389. * This procedure turns off the floppy drive motor, so
  390. * that we enter the kernel in a known state, and
  391. * don't have to worry about it later.
  392. */
  393. kill_motor:
  394. push dx
  395. mov dx,#0x3f2
  396. mov al,#0
  397. outb
  398. pop dx
  399. ret
  400.  
  401. gdt:
  402. .word 0,0,0,0 | dummy
  403.  
  404. .word 0x07FF | 8Mb - limit=2047 (2048*4096=8Mb)
  405. .word 0x0000 | base address=0
  406. .word 0x9A00 | code read/exec
  407. .word 0x00C0 | granularity=4096, 386
  408.  
  409. .word 0x07FF | 8Mb - limit=2047 (2048*4096=8Mb)
  410. .word 0x0000 | base address=0
  411. .word 0x9200 | data read/write
  412. .word 0x00C0 | granularity=4096, 386
  413.  
  414. idt_48:
  415. .word 0 | idt limit=0
  416. .word 0,0 | idt base=0L
  417.  
  418. gdt_48:
  419. .word 0x800 | gdt limit=2048, 256 GDT entries
  420. .word gdt,0x9 | gdt base = 0X9xxxx
  421.  
  422. msg1:
  423. .byte 13,10
  424. .ascii "Loading system ..."
  425. .byte 13,10,13,10
  426.  
  427. .text
  428. endtext:
  429. .data
  430. enddata:
  431. .bss
  432. endbss:
  433.  
  434. ------------------------------------------------------------------------
  435.  
  436. boot/head.s
  437.  
  438. /*
  439. * head.s contains the 32-bit startup code.
  440. *
  441. * NOTE!!! Startup happens at absolute address 0x00000000, which is also where
  442. * the page directory will exist. The startup code will be overwritten by
  443. * the page directory.
  444. */
  445. .text
  446. .globl _idt,_gdt,_pg_dir
  447. _pg_dir:
  448. startup_32:
  449. movl $0x10,%eax
  450. mov %ax,%ds
  451. mov %ax,%es
  452. mov %ax,%fs
  453. mov %ax,%gs
  454. lss _stack_start,%esp
  455. call setup_idt
  456. call setup_gdt
  457. movl $0x10,%eax # reload all the segment registers
  458. mov %ax,%ds # after changing gdt. CS was already
  459. mov %ax,%es # reloaded in 'setup_gdt'
  460. mov %ax,%fs
  461. mov %ax,%gs
  462. lss _stack_start,%esp
  463. xorl %eax,%eax
  464. 1: incl %eax # check that A20 really IS enabled
  465. movl %eax,0x000000
  466. cmpl %eax,0x100000
  467. je 1b
  468. movl %cr0,%eax # check math chip
  469. andl $0x80000011,%eax # Save PG,ET,PE
  470. testl $0x10,%eax
  471. jne 1f # ET is set - 387 is present
  472. orl $4,%eax # else set emulate bit
  473. 1: movl %eax,%cr0
  474. jmp after_page_tables
  475.  
  476. /*
  477. * setup_idt
  478. *
  479. * sets up a idt with 256 entries pointing to
  480. * ignore_int, interrupt gates. It then loads
  481. * idt. Everything that wants to install itself
  482. * in the idt-table may do so themselves. Interrupts
  483. * are enabled elsewhere, when we can be relatively
  484. * sure everything is ok. This routine will be over-
  485. * written by the page tables.
  486. */
  487. setup_idt:
  488. lea ignore_int,%edx
  489. movl $0x00080000,%eax
  490. movw %dx,%ax /* selector = 0x0008 = cs */
  491. movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
  492.  
  493. lea _idt,%edi
  494. mov $256,%ecx
  495. rp_sidt:
  496. movl %eax,(%edi)
  497. movl %edx,4(%edi)
  498. addl $8,%edi
  499. dec %ecx
  500. jne rp_sidt
  501. lidt idt_descr
  502. ret
  503.  
  504. /*
  505. * setup_gdt
  506. *
  507. * This routines sets up a new gdt and loads it.
  508. * Only two entries are currently built, the same
  509. * ones that were built in init.s. The routine
  510. * is VERY complicated at two whole lines, so this
  511. * rather long comment is certainly needed :-).
  512. * This routine will beoverwritten by the page tables.
  513. */
  514. setup_gdt:
  515. lgdt gdt_descr
  516. ret
  517.  
  518. .org 0x1000
  519. pg0:
  520.  
  521. .org 0x2000
  522. pg1:
  523.  
  524. .org 0x3000
  525. pg2: # This is not used yet, but if you
  526. # want to expand past 8 Mb, you'll have
  527. # to use it.
  528.  
  529. .org 0x4000
  530. after_page_tables:
  531. pushl $0 # These are the parameters to main :-)
  532. pushl $0
  533. pushl $0
  534. pushl $L6 # return address for main, if it decides to.
  535. pushl $_main
  536. jmp setup_paging
  537. L6:
  538. jmp L6 # main should never return here, but
  539. # just in case, we know what happens.
  540.  
  541. /* This is the default interrupt "handler" :-) */
  542. .align 2
  543. ignore_int:
  544. incb 0xb8000+160 # put something on the screen
  545. movb $2,0xb8000+161 # so that we know something
  546. iret # happened
  547.  
  548.  
  549. /*
  550. * Setup_paging
  551. *
  552. * This routine sets up paging by setting the page bit
  553. * in cr0. The page tables are set up, identity-mapping
  554. * the first 8MB. The pager assumes that no illegal
  555. * addresses are produced (ie >4Mb on a 4Mb machine).
  556. *
  557. * NOTE! Although all physical memory should be identity
  558. * mapped by this routine, only the kernel page functions
  559. * use the >1Mb addresses directly. All "normal" functions
  560. * use just the lower 1Mb, or the local data space, which
  561. * will be mapped to some other place - mm keeps track of
  562. * that.
  563. *
  564. * For those with more memory than 8 Mb - tough luck. I've
  565. * not got it, why should you :-) The source is here. Change
  566. * it. (Seriously - it shouldn't be too difficult. Mostly
  567. * change some constants etc. I left it at 8Mb, as my machine
  568. * even cannot be extended past that (ok, but it was cheap :-)
  569. * I've tried to show which constants to change by having
  570. * some kind of marker at them (search for "8Mb"), but I
  571. * won't guarantee that's all :-( )
  572. */
  573. .align 2
  574. setup_paging:
  575. movl $1024*3,%ecx
  576. xorl %eax,%eax
  577. xorl %edi,%edi /* pg_dir is at 0x000 */
  578. cld;rep;stosl
  579. movl $pg0+7,_pg_dir /* set present bit/user r/w */
  580. movl $pg1+7,_pg_dir+4 /* --------- " " --------- */
  581. movl $pg1+4092,%edi
  582. movl $0x7ff007,%eax /* 8Mb - 4096 + 7 (r/w user,p) */
  583. std
  584. 1: stosl /* fill pages backwards - more efficient :-) */
  585. subl $0x1000,%eax
  586. jge 1b
  587. xorl %eax,%eax /* pg_dir is at 0x0000 */
  588. movl %eax,%cr3 /* cr3 - page directory start */
  589. movl %cr0,%eax
  590. orl $0x80000000,%eax
  591. movl %eax,%cr0 /* set paging (PG) bit */
  592. ret /* this also flushes prefetch-queue */
  593.  
  594. .align 2
  595. .word 0
  596. idt_descr:
  597. .word 256*8-1 # idt contains 256 entries
  598. .long _idt
  599. .align 2
  600. .word 0
  601. gdt_descr:
  602. .word 256*8-1 # so does gdt (not that that's any
  603. .long _gdt # magic number, but it works for me :^)
  604.  
  605. .align 3
  606. _idt: .fill 256,8,0 # idt is uninitialized
  607.  
  608. _gdt: .quad 0x0000000000000000 /* NULL descriptor */
  609. .quad 0x00c09a00000007ff /* 8Mb */
  610. .quad 0x00c09200000007ff /* 8Mb */
  611. .quad 0x0000000000000000 /* TEMPORARY - don't use */
  612. .fill 252,8,0 /* space for LDT's and TSS's etc */
  613.  
  614. ------------------------------------------------------------------------
  615.  
  616. fs/bitmap.c
  617.  
  618. /* bitmap.c contains the code that handles the inode and block bitmaps */
  619. #include <string.h>
  620.  
  621. #include <linux/sched.h>
  622. #include <linux/kernel.h>
  623.  
  624. #define clear_block(addr) \
  625. __asm__("cld\n\t" \
  626. "rep\n\t" \
  627. "stosl" \
  628. ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
  629.  
  630. #define set_bit(nr,addr) ({\
  631. register int res __asm__("ax"); \
  632. __asm__("btsl %2,%3\n\tsetb %%al":"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
  633. res;})
  634.  
  635. #define clear_bit(nr,addr) ({\
  636. register int res __asm__("ax"); \
  637. __asm__("btrl %2,%3\n\tsetnb %%al":"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
  638. res;})
  639.  
  640. #define find_first_zero(addr) ({ \
  641. int __res; \
  642. __asm__("cld\n" \
  643. "1:\tlodsl\n\t" \
  644. "notl %%eax\n\t" \
  645. "bsfl %%eax,%%edx\n\t" \
  646. "je 2f\n\t" \
  647. "addl %%edx,%%ecx\n\t" \
  648. "jmp 3f\n" \
  649. "2:\taddl $32,%%ecx\n\t" \
  650. "cmpl $8192,%%ecx\n\t" \
  651. "jl 1b\n" \
  652. "3:" \
  653. :"=c" (__res):"c" (0),"S" (addr):"ax","dx","si"); \
  654. __res;})
  655.  
  656. void free_block(int dev, int block)
  657. {
  658. struct super_block * sb;
  659. struct buffer_head * bh;
  660.  
  661. if (!(sb = get_super(dev)))
  662. panic("trying to free block on nonexistent device");
  663. if (block < sb->s_firstdatazone || block >= sb->s_nzones)
  664. panic("trying to free block not in datazone");
  665. bh = get_hash_table(dev,block);
  666. if (bh) {
  667. if (bh->b_count != 1) {
  668. printk("trying to free block (%04x:%d), count=%d\n",
  669. dev,block,bh->b_count);
  670. return;
  671. }
  672. bh->b_dirt=0;
  673. bh->b_uptodate=0;
  674. brelse(bh);
  675. }
  676. block -= sb->s_firstdatazone - 1 ;
  677. if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {
  678. printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);
  679. panic("free_block: bit already cleared");
  680. }
  681. sb->s_zmap[block/8192]->b_dirt = 1;
  682. }
  683.  
  684. int new_block(int dev)
  685. {
  686. struct buffer_head * bh;
  687. struct super_block * sb;
  688. int i,j;
  689.  
  690. if (!(sb = get_super(dev)))
  691. panic("trying to get new block from nonexistant device");
  692. j = 8192;
  693. for (i=0 ; i<8 ; i++)
  694. if (bh=sb->s_zmap[i])
  695. if ((j=find_first_zero(bh->b_data))<8192)
  696. break;
  697. if (i>=8 || !bh || j>=8192)
  698. return 0;
  699. if (set_bit(j,bh->b_data))
  700. panic("new_block: bit already set");
  701. bh->b_dirt = 1;
  702. j += i*8192 + sb->s_firstdatazone-1;
  703. if (j >= sb->s_nzones)
  704. return 0;
  705. if (!(bh=getblk(dev,j)))
  706. panic("new_block: cannot get block");
  707. if (bh->b_count != 1)
  708. panic("new block: count is != 1");
  709. clear_block(bh->b_data);
  710. bh->b_uptodate = 1;
  711. bh->b_dirt = 1;
  712. brelse(bh);
  713. return j;
  714. }
  715.  
  716. void free_inode(struct m_inode * inode)
  717. {
  718. struct super_block * sb;
  719. struct buffer_head * bh;
  720.  
  721. if (!inode)
  722. return;
  723. if (!inode->i_dev) {
  724. memset(inode,0,sizeof(*inode));
  725. return;
  726. }
  727. if (inode->i_count>1) {
  728. printk("trying to free inode with count=%d\n",inode->i_count);
  729. panic("free_inode");
  730. }
  731. if (inode->i_nlinks)
  732. panic("trying to free inode with links");
  733. if (!(sb = get_super(inode->i_dev)))
  734. panic("trying to free inode on nonexistent device");
  735. if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)
  736. panic("trying to free inode 0 or nonexistant inode");
  737. if (!(bh=sb->s_imap[inode->i_num>>13]))
  738. panic("nonexistent imap in superblock");
  739. if (clear_bit(inode->i_num&8191,bh->b_data))
  740. panic("free_inode: bit already cleared");
  741. bh->b_dirt = 1;
  742. memset(inode,0,sizeof(*inode));
  743. }
  744.  
  745. struct m_inode * new_inode(int dev)
  746. {
  747. struct m_inode * inode;
  748. struct super_block * sb;
  749. struct buffer_head * bh;
  750. int i,j;
  751.  
  752. if (!(inode=get_empty_inode()))
  753. return NULL;
  754. if (!(sb = get_super(dev)))
  755. panic("new_inode with unknown device");
  756. j = 8192;
  757. for (i=0 ; i<8 ; i++)
  758. if (bh=sb->s_imap[i])
  759. if ((j=find_first_zero(bh->b_data))<8192)
  760. break;
  761. if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) {
  762. iput(inode);
  763. return NULL;
  764. }
  765. if (set_bit(j,bh->b_data))
  766. panic("new_inode: bit already set");
  767. bh->b_dirt = 1;
  768. inode->i_count=1;
  769. inode->i_nlinks=1;
  770. inode->i_dev=dev;
  771. inode->i_dirt=1;
  772. inode->i_num = j + i*8192;
  773. inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  774. return inode;
  775. }
  776.  
  777. ------------------------------------------------------------------------
  778.  
  779. fs/block_dev.c
  780.  
  781. #include <errno.h>
  782.  
  783. #include <linux/fs.h>
  784. #include <linux/kernel.h>
  785. #include <asm/segment.h>
  786.  
  787. #define NR_BLK_DEV ((sizeof (rd_blk))/(sizeof (rd_blk[0])))
  788.  
  789. int block_write(int dev, long * pos, char * buf, int count)
  790. {
  791. int block = *pos / BLOCK_SIZE;
  792. int offset = *pos % BLOCK_SIZE;
  793. int chars;
  794. int written = 0;
  795. struct buffer_head * bh;
  796. register char * p;
  797.  
  798. while (count>0) {
  799. bh = bread(dev,block);
  800. if (!bh)
  801. return written?written:-EIO;
  802. chars = (count<BLOCK_SIZE) ? count : BLOCK_SIZE;
  803. p = offset + bh->b_data;
  804. offset = 0;
  805. block++;
  806. *pos += chars;
  807. written += chars;
  808. count -= chars;
  809. while (chars-->0)
  810. *(p++) = get_fs_byte(buf++);
  811. bh->b_dirt = 1;
  812. brelse(bh);
  813. }
  814. return written;
  815. }
  816.  
  817. int block_read(int dev, unsigned long * pos, char * buf, int count)
  818. {
  819. int block = *pos / BLOCK_SIZE;
  820. int offset = *pos % BLOCK_SIZE;
  821. int chars;
  822. int read = 0;
  823. struct buffer_head * bh;
  824. register char * p;
  825.  
  826. while (count>0) {
  827. bh = bread(dev,block);
  828. if (!bh)
  829. return read?read:-EIO;
  830. chars = (count<BLOCK_SIZE) ? count : BLOCK_SIZE;
  831. p = offset + bh->b_data;
  832. offset = 0;
  833. block++;
  834. *pos += chars;
  835. read += chars;
  836. count -= chars;
  837. while (chars-->0)
  838. put_fs_byte(*(p++),buf++);
  839. bh->b_dirt = 1;
  840. brelse(bh);
  841. }
  842. return read;
  843. }
  844.  
  845. extern void rw_hd(int rw, struct buffer_head * bh);
  846.  
  847. typedef void (*blk_fn)(int rw, struct buffer_head * bh);
  848.  
  849. static blk_fn rd_blk[]={
  850. NULL, /* nodev */
  851. NULL, /* dev mem */
  852. NULL, /* dev fd */
  853. rw_hd, /* dev hd */
  854. NULL, /* dev ttyx */
  855. NULL, /* dev tty */
  856. NULL}; /* dev lp */
  857.  
  858. void ll_rw_block(int rw, struct buffer_head * bh)
  859. {
  860. blk_fn blk_addr;
  861. unsigned int major;
  862.  
  863. if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV || !(blk_addr=rd_blk[major]))
  864. panic("Trying to read nonexistent block-device");
  865. blk_addr(rw, bh);
  866. }
  867.  
  868. ------------------------------------------------------------------------
  869.  
  870. fs/buffer.c
  871.  
  872. /*
  873. * 'buffer.c' implements the buffer-cache functions. Race-conditions have
  874. * been avoided by NEVER letting a interrupt change a buffer (except for the
  875. * data, of course), but instead letting the caller do it. NOTE! As interrupts
  876. * can wake up a caller, some cli-sti sequences are needed to check for
  877. * sleep-on-calls. These should be extremely quick, though (I hope).
  878. */
  879.  
  880. #include <linux/config.h>
  881. #include <linux/sched.h>
  882. #include <linux/kernel.h>
  883. #include <asm/system.h>
  884.  
  885. #if (BUFFER_END & 0xfff)
  886. #error "Bad BUFFER_END value"
  887. #endif
  888.  
  889. #if (BUFFER_END > 0xA0000 && BUFFER_END <= 0x100000)
  890. #error "Bad BUFFER_END value"
  891. #endif
  892.  
  893. extern int end;
  894. struct buffer_head * start_buffer = (struct buffer_head *) &end;
  895. struct buffer_head * hash_table[NR_HASH];
  896. static struct buffer_head * free_list;
  897. static struct task_struct * buffer_wait = NULL;
  898. int NR_BUFFERS = 0;
  899.  
  900. static inline void wait_on_buffer(struct buffer_head * bh)
  901. {
  902. cli();
  903. while (bh->b_lock)
  904. sleep_on(&bh->b_wait);
  905. sti();
  906. }
  907.  
  908. int sys_sync(void)
  909. {
  910. int i;
  911. struct buffer_head * bh;
  912.  
  913. sync_inodes(); /* write out inodes into buffers */
  914. bh = start_buffer;
  915. for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
  916. wait_on_buffer(bh);
  917. if (bh->b_dirt)
  918. ll_rw_block(WRITE,bh);
  919. }
  920. return 0;
  921. }
  922.  
  923. static int sync_dev(int dev)
  924. {
  925. int i;
  926. struct buffer_head * bh;
  927.  
  928. bh = start_buffer;
  929. for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
  930. if (bh->b_dev != dev)
  931. continue;
  932. wait_on_buffer(bh);
  933. if (bh->b_dirt)
  934. ll_rw_block(WRITE,bh);
  935. }
  936. return 0;
  937. }
  938.  
  939. #define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
  940. #define hash(dev,block) hash_table[_hashfn(dev,block)]
  941.  
  942. static inline void remove_from_queues(struct buffer_head * bh)
  943. {
  944. /* remove from hash-queue */
  945. if (bh->b_next)
  946. bh->b_next->b_prev = bh->b_prev;
  947. if (bh->b_prev)
  948. bh->b_prev->b_next = bh->b_next;
  949. if (hash(bh->b_dev,bh->b_blocknr) == bh)
  950. hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
  951. /* remove from free list */
  952. if (!(bh->b_prev_free) || !(bh->b_next_free))
  953. panic("Free block list corrupted");
  954. bh->b_prev_free->b_next_free = bh->b_next_free;
  955. bh->b_next_free->b_prev_free = bh->b_prev_free;
  956. if (free_list == bh)
  957. free_list = bh->b_next_free;
  958. }
  959.  
  960. static inline void insert_into_queues(struct buffer_head * bh)
  961. {
  962. /* put at end of free list */
  963. bh->b_next_free = free_list;
  964. bh->b_prev_free = free_list->b_prev_free;
  965. free_list->b_prev_free->b_next_free = bh;
  966. free_list->b_prev_free = bh;
  967. /* put the buffer in new hash-queue if it has a device */
  968. bh->b_prev = NULL;
  969. bh->b_next = NULL;
  970. if (!bh->b_dev)
  971. return;
  972. bh->b_next = hash(bh->b_dev,bh->b_blocknr);
  973. hash(bh->b_dev,bh->b_blocknr) = bh;
  974. bh->b_next->b_prev = bh;
  975. }
  976.  
  977. static struct buffer_head * find_buffer(int dev, int block)
  978. {
  979. struct buffer_head * tmp;
  980.  
  981. for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
  982. if (tmp->b_dev==dev && tmp->b_blocknr==block)
  983. return tmp;
  984. return NULL;
  985. }
  986.  
  987. /*
  988. * Why like this, I hear you say... The reason is race-conditions.
  989. * As we don't lock buffers (unless we are readint them, that is),
  990. * something might happen to it while we sleep (ie a read-error
  991. * will force it bad). This shouldn't really happen currently, but
  992. * the code is ready.
  993. */
  994. struct buffer_head * get_hash_table(int dev, int block)
  995. {
  996. struct buffer_head * bh;
  997.  
  998. repeat:
  999. if (!(bh=find_buffer(dev,block)))
  1000. return NULL;
  1001. bh->b_count++;
  1002. wait_on_buffer(bh);
  1003. if (bh->b_dev != dev || bh->b_blocknr != block) {
  1004. brelse(bh);
  1005. goto repeat;
  1006. }
  1007. return bh;
  1008. }
  1009.  
  1010. /*
  1011. * Ok, this is getblk, and it isn't very clear, again to hinder
  1012. * race-conditions. Most of the code is seldom used, (ie repeating),
  1013. * so it should be much more efficient than it looks.
  1014. */
  1015. struct buffer_head * getblk(int dev,int block)
  1016. {
  1017. struct buffer_head * tmp;
  1018.  
  1019. repeat:
  1020. if (tmp=get_hash_table(dev,block))
  1021. return tmp;
  1022. tmp = free_list;
  1023. do {
  1024. if (!tmp->b_count) {
  1025. wait_on_buffer(tmp); /* we still have to wait */
  1026. if (!tmp->b_count) /* on it, it might be dirty */
  1027. break;
  1028. }
  1029. tmp = tmp->b_next_free;
  1030. } while (tmp != free_list || (tmp=NULL));
  1031. /* Kids, don't try THIS at home ^^^^^. Magic */
  1032. if (!tmp) {
  1033. printk("Sleeping on free buffer ..");
  1034. sleep_on(&buffer_wait);
  1035. printk("ok\n");
  1036. goto repeat;
  1037. }
  1038. tmp->b_count++;
  1039. remove_from_queues(tmp);
  1040. /*
  1041. * Now, when we know nobody can get to this node (as it's removed from the
  1042. * free list), we write it out. We can sleep here without fear of race-
  1043. * conditions.
  1044. */
  1045. if (tmp->b_dirt)
  1046. sync_dev(tmp->b_dev);
  1047. /* update buffer contents */
  1048. tmp->b_dev=dev;
  1049. tmp->b_blocknr=block;
  1050. tmp->b_dirt=0;
  1051. tmp->b_uptodate=0;
  1052. /* NOTE!! While we possibly slept in sync_dev(), somebody else might have
  1053. * added "this" block already, so check for that. Thank God for goto's.
  1054. */
  1055. if (find_buffer(dev,block)) {
  1056. tmp->b_dev=0; /* ok, someone else has beaten us */
  1057. tmp->b_blocknr=0; /* to it - free this block and */
  1058. tmp->b_count=0; /* try again */
  1059. insert_into_queues(tmp);
  1060. goto repeat;
  1061. }
  1062. /* and then insert into correct position */
  1063. insert_into_queues(tmp);
  1064. return tmp;
  1065. }
  1066.  
  1067. void brelse(struct buffer_head * buf)
  1068. {
  1069. if (!buf)
  1070. return;
  1071. wait_on_buffer(buf);
  1072. if (!(buf->b_count--))
  1073. panic("Trying to free free buffer");
  1074. wake_up(&buffer_wait);
  1075. }
  1076.  
  1077. /*
  1078. * bread() reads a specified block and returns the buffer that contains
  1079. * it. It returns NULL if the block was unreadable.
  1080. */
  1081. struct buffer_head * bread(int dev,int block)
  1082. {
  1083. struct buffer_head * bh;
  1084.  
  1085. if (!(bh=getblk(dev,block)))
  1086. panic("bread: getblk returned NULL\n");
  1087. if (bh->b_uptodate)
  1088. return bh;
  1089. ll_rw_block(READ,bh);
  1090. if (bh->b_uptodate)
  1091. return bh;
  1092. brelse(bh);
  1093. return (NULL);
  1094. }
  1095.  
  1096. void buffer_init(void)
  1097. {
  1098. struct buffer_head * h = start_buffer;
  1099. void * b = (void *) BUFFER_END;
  1100. int i;
  1101.  
  1102. while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {
  1103. h->b_dev = 0;
  1104. h->b_dirt = 0;
  1105. h->b_count = 0;
  1106. h->b_lock = 0;
  1107. h->b_uptodate = 0;
  1108. h->b_wait = NULL;
  1109. h->b_next = NULL;
  1110. h->b_prev = NULL;
  1111. h->b_data = (char *) b;
  1112. h->b_prev_free = h-1;
  1113. h->b_next_free = h+1;
  1114. h++;
  1115. NR_BUFFERS++;
  1116. if (b == (void *) 0x100000)
  1117. b = (void *) 0xA0000;
  1118. }
  1119. h--;
  1120. free_list = start_buffer;
  1121. free_list->b_prev_free = h;
  1122. h->b_next_free = free_list;
  1123. for (i=0;i<NR_HASH;i++)
  1124. hash_table[i]=NULL;
  1125. }
  1126.  
  1127. ------------------------------------------------------------------------
  1128.  
  1129. fs/char_dev.c
  1130.  
  1131. #include <errno.h>
  1132.  
  1133. #include <linux/sched.h>
  1134. #include <linux/kernel.h>
  1135.  
  1136. extern int tty_read(unsigned minor,char * buf,int count);
  1137. extern int tty_write(unsigned minor,char * buf,int count);
  1138.  
  1139. static int rw_ttyx(int rw,unsigned minor,char * buf,int count);
  1140. static int rw_tty(int rw,unsigned minor,char * buf,int count);
  1141.  
  1142. typedef (*crw_ptr)(int rw,unsigned minor,char * buf,int count);
  1143.  
  1144. #define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))
  1145.  
  1146. static crw_ptr crw_table[]={
  1147. NULL, /* nodev */
  1148. NULL, /* /dev/mem */
  1149. NULL, /* /dev/fd */
  1150. NULL, /* /dev/hd */
  1151. rw_ttyx, /* /dev/ttyx */
  1152. rw_tty, /* /dev/tty */
  1153. NULL, /* /dev/lp */
  1154. NULL}; /* unnamed pipes */
  1155.  
  1156. static int rw_ttyx(int rw,unsigned minor,char * buf,int count)
  1157. {
  1158. return ((rw==READ)?tty_read(minor,buf,count):
  1159. tty_write(minor,buf,count));
  1160. }
  1161.  
  1162. static int rw_tty(int rw,unsigned minor,char * buf,int count)
  1163. {
  1164. if (current->tty<0)
  1165. return -EPERM;
  1166. return rw_ttyx(rw,current->tty,buf,count);
  1167. }
  1168.  
  1169. int rw_char(int rw,int dev, char * buf, int count)
  1170. {
  1171. crw_ptr call_addr;
  1172.  
  1173. if (MAJOR(dev)>=NRDEVS)
  1174. panic("rw_char: dev>NRDEV");
  1175. if (!(call_addr=crw_table[MAJOR(dev)])) {
  1176. printk("dev: %04x\n",dev);
  1177. panic("Trying to r/w from/to nonexistent character device");
  1178. }
  1179. return call_addr(rw,MINOR(dev),buf,count);
  1180. }
  1181.  
  1182. ------------------------------------------------------------------------
  1183.  
  1184. fs/exec.c
  1185.  
  1186. #include <errno.h>
  1187. #include <sys/stat.h>
  1188. #include <a.out.h>
  1189.  
  1190. #include <linux/fs.h>
  1191. #include <linux/sched.h>
  1192. #include <linux/kernel.h>
  1193. #include <linux/mm.h>
  1194. #include <asm/segment.h>
  1195.  
  1196. extern int sys_exit(int exit_code);
  1197. extern int sys_close(int fd);
  1198.  
  1199. /*
  1200. * MAX_ARG_PAGES defines the number of pages allocated for arguments
  1201. * and envelope for the new program. 32 should suffice, this gives
  1202. * a maximum env+arg of 128kB !
  1203. */
  1204. #define MAX_ARG_PAGES 32
  1205.  
  1206. #define cp_block(from,to) \
  1207. __asm__("pushl $0x10\n\t" \
  1208. "pushl $0x17\n\t" \
  1209. "pop %%es\n\t" \
  1210. "cld\n\t" \
  1211. "rep\n\t" \
  1212. "movsl\n\t" \
  1213. "pop %%es" \
  1214. ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
  1215. :"cx","di","si")
  1216.  
  1217. /*
  1218. * read_head() reads blocks 1-6 (not 0). Block 0 has already been
  1219. * read for header information.
  1220. */
  1221. int read_head(struct m_inode * inode,int blocks)
  1222. {
  1223. struct buffer_head * bh;
  1224. int count;
  1225.  
  1226. if (blocks>6)
  1227. blocks=6;
  1228. for(count = 0 ; count<blocks ; count++) {
  1229. if (!inode->i_zone[count+1])
  1230. continue;
  1231. if (!(bh=bread(inode->i_dev,inode->i_zone[count+1])))
  1232. return -1;
  1233. cp_block(bh->b_data,count*BLOCK_SIZE);
  1234. brelse(bh);
  1235. }
  1236. return 0;
  1237. }
  1238.  
  1239. int read_ind(int dev,int ind,long size,unsigned long offset)
  1240. {
  1241. struct buffer_head * ih, * bh;
  1242. unsigned short * table,block;
  1243.  
  1244. if (size<=0)
  1245. panic("size<=0 in read_ind");
  1246. if (size>512*BLOCK_SIZE)
  1247. size=512*BLOCK_SIZE;
  1248. if (!ind)
  1249. return 0;
  1250. if (!(ih=bread(dev,ind)))
  1251. return -1;
  1252. table = (unsigned short *) ih->b_data;
  1253. while (size>0) {
  1254. if (block=*(table++))
  1255. if (!(bh=bread(dev,block))) {
  1256. brelse(ih);
  1257. return -1;
  1258. } else {
  1259. cp_block(bh->b_data,offset);
  1260. brelse(bh);
  1261. }
  1262. size -= BLOCK_SIZE;
  1263. offset += BLOCK_SIZE;
  1264. }
  1265. brelse(ih);
  1266. return 0;
  1267. }
  1268.  
  1269. /*
  1270. * read_area() reads an area into %fs:mem.
  1271. */
  1272. int read_area(struct m_inode * inode,long size)
  1273. {
  1274. struct buffer_head * dind;
  1275. unsigned short * table;
  1276. int i,count;
  1277.  
  1278. if ((i=read_head(inode,(size+BLOCK_SIZE-1)/BLOCK_SIZE)) ||
  1279. (size -= BLOCK_SIZE*6)<=0)
  1280. return i;
  1281. if ((i=read_ind(inode->i_dev,inode->i_zone[7],size,BLOCK_SIZE*6)) ||
  1282. (size -= BLOCK_SIZE*512)<=0)
  1283. return i;
  1284. if (!(i=inode->i_zone[8]))
  1285. return 0;
  1286. if (!(dind = bread(inode->i_dev,i)))
  1287. return -1;
  1288. table = (unsigned short *) dind->b_data;
  1289. for(count=0 ; count<512 ; count++)
  1290. if ((i=read_ind(inode->i_dev,*(table++),size,
  1291. BLOCK_SIZE*(518+count))) || (size -= BLOCK_SIZE*512)<=0)
  1292. return i;
  1293. panic("Impossibly long executable");
  1294. }
  1295.  
  1296. /*
  1297. * create_tables() parses the env- and arg-strings in new user
  1298. * memory and creates the pointer tables from them, and puts their
  1299. * addresses on the "stack", returning the new stack pointer value.
  1300. */
  1301. static unsigned long * create_tables(char * p,int argc,int envc)
  1302. {
  1303. unsigned long *argv,*envp;
  1304. unsigned long * sp;
  1305.  
  1306. sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
  1307. sp -= envc+1;
  1308. envp = sp;
  1309. sp -= argc+1;
  1310. argv = sp;
  1311. put_fs_long((unsigned long)envp,--sp);
  1312. put_fs_long((unsigned long)argv,--sp);
  1313. put_fs_long((unsigned long)argc,--sp);
  1314. while (argc-->0) {
  1315. put_fs_long((unsigned long) p,argv++);
  1316. while (get_fs_byte(p++)) /* nothing */ ;
  1317. }
  1318. put_fs_long(0,argv);
  1319. while (envc-->0) {
  1320. put_fs_long((unsigned long) p,envp++);
  1321. while (get_fs_byte(p++)) /* nothing */ ;
  1322. }
  1323. put_fs_long(0,envp);
  1324. return sp;
  1325. }
  1326.  
  1327. /*
  1328. * count() counts the number of arguments/envelopes
  1329. */
  1330. static int count(char ** argv)
  1331. {
  1332. int i=0;
  1333. char ** tmp;
  1334.  
  1335. if (tmp = argv)
  1336. while (get_fs_long((unsigned long *) (tmp++)))
  1337. i++;
  1338.  
  1339. return i;
  1340. }
  1341.  
  1342. /*
  1343. * 'copy_string()' copies argument/envelope strings from user
  1344. * memory to free pages in kernel mem. These are in a format ready
  1345. * to be put directly into the top of new user memory.
  1346. */
  1347. static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
  1348. unsigned long p)
  1349. {
  1350. int len,i;
  1351. char *tmp;
  1352.  
  1353. while (argc-- > 0) {
  1354. if (!(tmp = (char *)get_fs_long(((unsigned long *) argv)+argc)))
  1355. panic("argc is wrong");
  1356. len=0; /* remember zero-padding */
  1357. do {
  1358. len++;
  1359. } while (get_fs_byte(tmp++));
  1360. if (p-len < 0) /* this shouldn't happen - 128kB */
  1361. return 0;
  1362. i = ((unsigned) (p-len)) >> 12;
  1363. while (i<MAX_ARG_PAGES && !page[i]) {
  1364. if (!(page[i]=get_free_page()))
  1365. return 0;
  1366. i++;
  1367. }
  1368. do {
  1369. --p;
  1370. if (!page[p/PAGE_SIZE])
  1371. panic("nonexistent page in exec.c");
  1372. ((char *) page[p/PAGE_SIZE])[p%PAGE_SIZE] =
  1373. get_fs_byte(--tmp);
  1374. } while (--len);
  1375. }
  1376. return p;
  1377. }
  1378.  
  1379. static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
  1380. {
  1381. unsigned long code_limit,data_limit,code_base,data_base;
  1382. int i;
  1383.  
  1384. code_limit = text_size+PAGE_SIZE -1;
  1385. code_limit &= 0xFFFFF000;
  1386. data_limit = 0x4000000;
  1387. code_base = get_base(current->ldt[1]);
  1388. data_base = code_base;
  1389. set_base(current->ldt[1],code_base);
  1390. set_limit(current->ldt[1],code_limit);
  1391. set_base(current->ldt[2],data_base);
  1392. set_limit(current->ldt[2],data_limit);
  1393. /* make sure fs points to the NEW data segment */
  1394. __asm__("pushl $0x17\n\tpop %%fs"::);
  1395. data_base += data_limit;
  1396. for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
  1397. data_base -= PAGE_SIZE;
  1398. if (page[i])
  1399. put_page(page[i],data_base);
  1400. }
  1401. return data_limit;
  1402. }
  1403.  
  1404. /*
  1405. * 'do_execve()' executes a new program.
  1406. */
  1407. int do_execve(unsigned long * eip,long tmp,char * filename,
  1408. char ** argv, char ** envp)
  1409. {
  1410. struct m_inode * inode;
  1411. struct buffer_head * bh;
  1412. struct exec ex;
  1413. unsigned long page[MAX_ARG_PAGES];
  1414. int i,argc,envc;
  1415. unsigned long p;
  1416.  
  1417. if ((0xffff & eip[1]) != 0x000f)
  1418. panic("execve called from supervisor mode");
  1419. for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
  1420. page[i]=0;
  1421. if (!(inode=namei(filename))) /* get executables inode */
  1422. return -ENOENT;
  1423. if (!S_ISREG(inode->i_mode)) { /* must be regular file */
  1424. iput(inode);
  1425. return -EACCES;
  1426. }
  1427. i = inode->i_mode;
  1428. if (current->uid && current->euid) {
  1429. if (current->euid == inode->i_uid)
  1430. i >>= 6;
  1431. else if (current->egid == inode->i_gid)
  1432. i >>= 3;
  1433. } else if (i & 0111)
  1434. i=1;
  1435. if (!(i & 1)) {
  1436. iput(inode);
  1437. return -ENOEXEC;
  1438. }
  1439. if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
  1440. iput(inode);
  1441. return -EACCES;
  1442. }
  1443. ex = *((struct exec *) bh->b_data); /* read exec-header */
  1444. brelse(bh);
  1445. if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
  1446. ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
  1447. inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
  1448. iput(inode);
  1449. return -ENOEXEC;
  1450. }
  1451. if (N_TXTOFF(ex) != BLOCK_SIZE)
  1452. panic("N_TXTOFF != BLOCK_SIZE. See a.out.h.");
  1453. argc = count(argv);
  1454. envc = count(envp);
  1455. p = copy_strings(envc,envp,page,PAGE_SIZE*MAX_ARG_PAGES-4);
  1456. p = copy_strings(argc,argv,page,p);
  1457. if (!p) {
  1458. for (i=0 ; i<MAX_ARG_PAGES ; i++)
  1459. free_page(page[i]);
  1460. iput(inode);
  1461. return -1;
  1462. }
  1463. /* OK, This is the point of no return */
  1464. for (i=0 ; i<32 ; i++)
  1465. current->sig_fn[i] = NULL;
  1466. for (i=0 ; i<NR_OPEN ; i++)
  1467. if ((current->close_on_exec>>i)&1)
  1468. sys_close(i);
  1469. current->close_on_exec = 0;
  1470. free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
  1471. free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
  1472. if (last_task_used_math == current)
  1473. last_task_used_math = NULL;
  1474. current->used_math = 0;
  1475. p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
  1476. p = (unsigned long) create_tables((char *)p,argc,envc);
  1477. current->brk = ex.a_bss +
  1478. (current->end_data = ex.a_data +
  1479. (current->end_code = ex.a_text));
  1480. current->start_stack = p & 0xfffff000;
  1481. i = read_area(inode,ex.a_text+ex.a_data);
  1482. iput(inode);
  1483. if (i<0)
  1484. sys_exit(-1);
  1485. i = ex.a_text+ex.a_data;
  1486. while (i&0xfff)
  1487. put_fs_byte(0,(char *) (i++));
  1488. eip[0] = ex.a_entry; /* eip, magic happens :-) */
  1489. eip[3] = p; /* stack pointer */
  1490. return 0;
  1491. }
  1492.  
  1493. ------------------------------------------------------------------------
  1494.  
  1495. fs/fcntl.c
  1496.  
  1497. #include <string.h>
  1498. #include <errno.h>
  1499. #include <linux/sched.h>
  1500. #include <linux/kernel.h>
  1501. #include <asm/segment.h>
  1502.  
  1503. #include <fcntl.h>
  1504. #include <sys/stat.h>
  1505.  
  1506. extern int sys_close(int fd);
  1507.  
  1508. static int dupfd(unsigned int fd, unsigned int arg)
  1509. {
  1510. if (fd >= NR_OPEN || !current->filp[fd])
  1511. return -EBADF;
  1512. if (arg >= NR_OPEN)
  1513. return -EINVAL;
  1514. while (arg < NR_OPEN)
  1515. if (current->filp[arg])
  1516. arg++;
  1517. else
  1518. break;
  1519. if (arg >= NR_OPEN)
  1520. return -EMFILE;
  1521. current->close_on_exec &= ~(1<<arg);
  1522. (current->filp[arg] = current->filp[fd])->f_count++;
  1523. return arg;
  1524. }
  1525.  
  1526. int sys_dup2(unsigned int oldfd, unsigned int newfd)
  1527. {
  1528. sys_close(newfd);
  1529. return dupfd(oldfd,newfd);
  1530. }
  1531.  
  1532. int sys_dup(unsigned int fildes)
  1533. {
  1534. return dupfd(fildes,0);
  1535. }
  1536.  
  1537. int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
  1538. {
  1539. struct file * filp;
  1540.  
  1541. if (fd >= NR_OPEN || !(filp = current->filp[fd]))
  1542. return -EBADF;
  1543. switch (cmd) {
  1544. case F_DUPFD:
  1545. return dupfd(fd,arg);
  1546. case F_GETFD:
  1547. return (current->close_on_exec>>fd)&1;
  1548. case F_SETFD:
  1549. if (arg&1)
  1550. current->close_on_exec |= (1<<fd);
  1551. else
  1552. current->close_on_exec &= ~(1<<fd);
  1553. return 0;
  1554. case F_GETFL:
  1555. return filp->f_flags;
  1556. case F_SETFL:
  1557. filp->f_flags &= ~(O_APPEND | O_NONBLOCK);
  1558. filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
  1559. return 0;
  1560. case F_GETLK: case F_SETLK: case F_SETLKW:
  1561. return -1;
  1562. default:
  1563. return -1;
  1564. }
  1565. }
  1566.  
  1567. ------------------------------------------------------------------------
  1568.  
  1569. fs/file_dev.c
  1570.  
  1571. #include <errno.h>
  1572. #include <fcntl.h>
  1573.  
  1574. #include <linux/sched.h>
  1575. #include <linux/kernel.h>
  1576. #include <asm/segment.h>
  1577.  
  1578. #define MIN(a,b) (((a)<(b))?(a):(b))
  1579. #define MAX(a,b) (((a)>(b))?(a):(b))
  1580.  
  1581. int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
  1582. {
  1583. int left,chars,nr;
  1584. struct buffer_head * bh;
  1585.  
  1586. if ((left=count)<=0)
  1587. return 0;
  1588. while (left) {
  1589. if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {
  1590. if (!(bh=bread(inode->i_dev,nr)))
  1591. break;
  1592. } else
  1593. bh = NULL;
  1594. nr = filp->f_pos % BLOCK_SIZE;
  1595. chars = MIN( BLOCK_SIZE-nr , left );
  1596. filp->f_pos += chars;
  1597. left -= chars;
  1598. if (bh) {
  1599. char * p = nr + bh->b_data;
  1600. while (chars-->0)
  1601. put_fs_byte(*(p++),buf++);
  1602. brelse(bh);
  1603. } else {
  1604. while (chars-->0)
  1605. put_fs_byte(0,buf++);
  1606. }
  1607. }
  1608. inode->i_atime = CURRENT_TIME;
  1609. return (count-left)?(count-left):-ERROR;
  1610. }
  1611.  
  1612. int file_write(struct m_inode * inode, struct file * filp, char * buf, int count)
  1613. {
  1614. off_t pos;
  1615. int block,c;
  1616. struct buffer_head * bh;
  1617. char * p;
  1618. int i=0;
  1619.  
  1620. /*
  1621. * ok, append may not work when many processes are writing at the same time
  1622. * but so what. That way leads to madness anyway.
  1623. */
  1624. if (filp->f_flags & O_APPEND)
  1625. pos = inode->i_size;
  1626. else
  1627. pos = filp->f_pos;
  1628. while (i<count) {
  1629. if (!(block = create_block(inode,pos/BLOCK_SIZE)))
  1630. break;
  1631. if (!(bh=bread(inode->i_dev,block)))
  1632. break;
  1633. c = pos % BLOCK_SIZE;
  1634. p = c + bh->b_data;
  1635. bh->b_dirt = 1;
  1636. c = BLOCK_SIZE-c;
  1637. if (c > count-i) c = count-i;
  1638. pos += c;
  1639. if (pos > inode->i_size) {
  1640. inode->i_size = pos;
  1641. inode->i_dirt = 1;
  1642. }
  1643. i += c;
  1644. while (c-->0)
  1645. *(p++) = get_fs_byte(buf++);
  1646. brelse(bh);
  1647. }
  1648. inode->i_mtime = CURRENT_TIME;
  1649. if (!(filp->f_flags & O_APPEND)) {
  1650. filp->f_pos = pos;
  1651. inode->i_ctime = CURRENT_TIME;
  1652. }
  1653. return (i?i:-1);
  1654. }
  1655.  
  1656. ------------------------------------------------------------------------
  1657.  
  1658. fs/file_table.c
  1659.  
  1660. #include <linux/fs.h>
  1661.  
  1662. struct file file_table[NR_FILE];
  1663.  
  1664. ------------------------------------------------------------------------
  1665.  
  1666. fs/inode.c
  1667.  
  1668. #include <string.h>
  1669.  
  1670. #include <linux/sched.h>
  1671. #include <linux/kernel.h>
  1672. #include <linux/mm.h>
  1673. #include <asm/system.h>
  1674.  
  1675. struct m_inode inode_table[NR_INODE]={{0,},};
  1676.  
  1677. static void read_inode(struct m_inode * inode);
  1678. static void write_inode(struct m_inode * inode);
  1679.  
  1680. static inline void wait_on_inode(struct m_inode * inode)
  1681. {
  1682. cli();
  1683. while (inode->i_lock)
  1684. sleep_on(&inode->i_wait);
  1685. sti();
  1686. }
  1687.  
  1688. static inline void lock_inode(struct m_inode * inode)
  1689. {
  1690. cli();
  1691. while (inode->i_lock)
  1692. sleep_on(&inode->i_wait);
  1693. inode->i_lock=1;
  1694. sti();
  1695. }
  1696.  
  1697. static inline void unlock_inode(struct m_inode * inode)
  1698. {
  1699. inode->i_lock=0;
  1700. wake_up(&inode->i_wait);
  1701. }
  1702.  
  1703. void sync_inodes(void)
  1704. {
  1705. int i;
  1706. struct m_inode * inode;
  1707.  
  1708. inode = 0+inode_table;
  1709. for(i=0 ; i<NR_INODE ; i++,inode++) {
  1710. wait_on_inode(inode);
  1711. if (inode->i_dirt && !inode->i_pipe)
  1712. write_inode(inode);
  1713. }
  1714. }
  1715.  
  1716. static int _bmap(struct m_inode * inode,int block,int create)
  1717. {
  1718. struct buffer_head * bh;
  1719. int i;
  1720.  
  1721. if (block<0)
  1722. panic("_bmap: block<0");
  1723. if (block >= 7+512+512*512)
  1724. panic("_bmap: block>big");
  1725. if (block<7) {
  1726. if (create && !inode->i_zone[block])
  1727. if (inode->i_zone[block]=new_block(inode->i_dev)) {
  1728. inode->i_ctime=CURRENT_TIME;
  1729. inode->i_dirt=1;
  1730. }
  1731. return inode->i_zone[block];
  1732. }
  1733. block -= 7;
  1734. if (block<512) {
  1735. if (create && !inode->i_zone[7])
  1736. if (inode->i_zone[7]=new_block(inode->i_dev)) {
  1737. inode->i_dirt=1;
  1738. inode->i_ctime=CURRENT_TIME;
  1739. }
  1740. if (!inode->i_zone[7])
  1741. return 0;
  1742. if (!(bh = bread(inode->i_dev,inode->i_zone[7])))
  1743. return 0;
  1744. i = ((unsigned short *) (bh->b_data))[block];
  1745. if (create && !i)
  1746. if (i=new_block(inode->i_dev)) {
  1747. ((unsigned short *) (bh->b_data))[block]=i;
  1748. bh->b_dirt=1;
  1749. }
  1750. brelse(bh);
  1751. return i;
  1752. }
  1753. block -= 512;
  1754. if (create && !inode->i_zone[8])
  1755. if (inode->i_zone[8]=new_block(inode->i_dev)) {
  1756. inode->i_dirt=1;
  1757. inode->i_ctime=CURRENT_TIME;
  1758. }
  1759. if (!inode->i_zone[8])
  1760. return 0;
  1761. if (!(bh=bread(inode->i_dev,inode->i_zone[8])))
  1762. return 0;
  1763. i = ((unsigned short *)bh->b_data)[block>>9];
  1764. if (create && !i)
  1765. if (i=new_block(inode->i_dev)) {
  1766. ((unsigned short *) (bh->b_data))[block>>9]=i;
  1767. bh->b_dirt=1;
  1768. }
  1769. brelse(bh);
  1770. if (!i)
  1771. return 0;
  1772. if (!(bh=bread(inode->i_dev,i)))
  1773. return 0;
  1774. i = ((unsigned short *)bh->b_data)[block&511];
  1775. if (create && !i)
  1776. if (i=new_block(inode->i_dev)) {
  1777. ((unsigned short *) (bh->b_data))[block&511]=i;
  1778. bh->b_dirt=1;
  1779. }
  1780. brelse(bh);
  1781. return i;
  1782. }
  1783.  
  1784. int bmap(struct m_inode * inode,int block)
  1785. {
  1786. return _bmap(inode,block,0);
  1787. }
  1788.  
  1789. int create_block(struct m_inode * inode, int block)
  1790. {
  1791. return _bmap(inode,block,1);
  1792. }
  1793.  
  1794. void iput(struct m_inode * inode)
  1795. {
  1796. if (!inode)
  1797. return;
  1798. wait_on_inode(inode);
  1799. if (!inode->i_count)
  1800. panic("iput: trying to free free inode");
  1801. if (inode->i_pipe) {
  1802. wake_up(&inode->i_wait);
  1803. if (--inode->i_count)
  1804. return;
  1805. free_page(inode->i_size);
  1806. inode->i_count=0;
  1807. inode->i_dirt=0;
  1808. inode->i_pipe=0;
  1809. return;
  1810. }
  1811. if (!inode->i_dev || inode->i_count>1) {
  1812. inode->i_count--;
  1813. return;
  1814. }
  1815. repeat:
  1816. if (!inode->i_nlinks) {
  1817. truncate(inode);
  1818. free_inode(inode);
  1819. return;
  1820. }
  1821. if (inode->i_dirt) {
  1822. write_inode(inode); /* we can sleep - so do again */
  1823. wait_on_inode(inode);
  1824. goto repeat;
  1825. }
  1826. inode->i_count--;
  1827. return;
  1828. }
  1829.  
  1830. static volatile int last_allocated_inode = 0;
  1831.  
  1832. struct m_inode * get_empty_inode(void)
  1833. {
  1834. struct m_inode * inode;
  1835. int inr;
  1836.  
  1837. while (1) {
  1838. inode = NULL;
  1839. inr = last_allocated_inode;
  1840. do {
  1841. if (!inode_table[inr].i_count) {
  1842. inode = inr + inode_table;
  1843. break;
  1844. }
  1845. inr++;
  1846. if (inr>=NR_INODE)
  1847. inr=0;
  1848. } while (inr != last_allocated_inode);
  1849. if (!inode) {
  1850. for (inr=0 ; inr<NR_INODE ; inr++)
  1851. printk("%04x: %6d\t",inode_table[inr].i_dev,
  1852. inode_table[inr].i_num);
  1853. panic("No free inodes in mem");
  1854. }
  1855. last_allocated_inode = inr;
  1856. wait_on_inode(inode);
  1857. while (inode->i_dirt) {
  1858. write_inode(inode);
  1859. wait_on_inode(inode);
  1860. }
  1861. if (!inode->i_count)
  1862. break;
  1863. }
  1864. memset(inode,0,sizeof(*inode));
  1865. inode->i_count = 1;
  1866. return inode;
  1867. }
  1868.  
  1869. struct m_inode * get_pipe_inode(void)
  1870. {
  1871. struct m_inode * inode;
  1872.  
  1873. if (!(inode = get_empty_inode()))
  1874. return NULL;
  1875. if (!(inode->i_size=get_free_page())) {
  1876. inode->i_count = 0;
  1877. return NULL;
  1878. }
  1879. inode->i_count = 2; /* sum of readers/writers */
  1880. PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
  1881. inode->i_pipe = 1;
  1882. return inode;
  1883. }
  1884.  
  1885. struct m_inode * iget(int dev,int nr)
  1886. {
  1887. struct m_inode * inode, * empty;
  1888.  
  1889. if (!dev)
  1890. panic("iget with dev==0");
  1891. empty = get_empty_inode();
  1892. inode = inode_table;
  1893. while (inode < NR_INODE+inode_table) {
  1894. if (inode->i_dev != dev || inode->i_num != nr) {
  1895. inode++;
  1896. continue;
  1897. }
  1898. wait_on_inode(inode);
  1899. if (inode->i_dev != dev || inode->i_num != nr) {
  1900. inode = inode_table;
  1901. continue;
  1902. }
  1903. inode->i_count++;
  1904. if (empty)
  1905. iput(empty);
  1906. return inode;
  1907. }
  1908. if (!empty)
  1909. return (NULL);
  1910. inode=empty;
  1911. inode->i_dev = dev;
  1912. inode->i_num = nr;
  1913. read_inode(inode);
  1914. return inode;
  1915. }
  1916.  
  1917. static void read_inode(struct m_inode * inode)
  1918. {
  1919. struct super_block * sb;
  1920. struct buffer_head * bh;
  1921. int block;
  1922.  
  1923. lock_inode(inode);
  1924. sb=get_super(inode->i_dev);
  1925. block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
  1926. (inode->i_num-1)/INODES_PER_BLOCK;
  1927. if (!(bh=bread(inode->i_dev,block)))
  1928. panic("unable to read i-node block");
  1929. *(struct d_inode *)inode =
  1930. ((struct d_inode *)bh->b_data)
  1931. [(inode->i_num-1)%INODES_PER_BLOCK];
  1932. brelse(bh);
  1933. unlock_inode(inode);
  1934. }
  1935.  
  1936. static void write_inode(struct m_inode * inode)
  1937. {
  1938. struct super_block * sb;
  1939. struct buffer_head * bh;
  1940. int block;
  1941.  
  1942. lock_inode(inode);
  1943. sb=get_super(inode->i_dev);
  1944. block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
  1945. (inode->i_num-1)/INODES_PER_BLOCK;
  1946. if (!(bh=bread(inode->i_dev,block)))
  1947. panic("unable to read i-node block");
  1948. ((struct d_inode *)bh->b_data)
  1949. [(inode->i_num-1)%INODES_PER_BLOCK] =
  1950. *(struct d_inode *)inode;
  1951. bh->b_dirt=1;
  1952. inode->i_dirt=0;
  1953. brelse(bh);
  1954. unlock_inode(inode);
  1955. }
  1956.  
  1957. ------------------------------------------------------------------------
  1958.  
  1959. fs/ioctl.c
  1960.  
  1961. #include <string.h>
  1962. #include <errno.h>
  1963. #include <sys/stat.h>
  1964.  
  1965. #include <linux/sched.h>
  1966.  
  1967. extern int tty_ioctl(int dev, int cmd, int arg);
  1968.  
  1969. typedef int (*ioctl_ptr)(int dev,int cmd,int arg);
  1970.  
  1971. #define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr)))
  1972.  
  1973. static ioctl_ptr ioctl_table[]={
  1974. NULL, /* nodev */
  1975. NULL, /* /dev/mem */
  1976. NULL, /* /dev/fd */
  1977. NULL, /* /dev/hd */
  1978. tty_ioctl, /* /dev/ttyx */
  1979. tty_ioctl, /* /dev/tty */
  1980. NULL, /* /dev/lp */
  1981. NULL}; /* named pipes */
  1982.  
  1983.  
  1984. int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
  1985. {
  1986. struct file * filp;
  1987. int dev,mode;
  1988.  
  1989. if (fd >= NR_OPEN || !(filp = current->filp[fd]))
  1990. return -EBADF;
  1991. mode=filp->f_inode->i_mode;
  1992. if (!S_ISCHR(mode) && !S_ISBLK(mode))
  1993. return -EINVAL;
  1994. dev = filp->f_inode->i_zone[0];
  1995. if (MAJOR(dev) >= NRDEVS)
  1996. panic("unknown device for ioctl");
  1997. if (!ioctl_table[MAJOR(dev)])
  1998. return -ENOTTY;
  1999. return ioctl_table[MAJOR(dev)](dev,cmd,arg);
  2000. }
  2001.  
  2002. ------------------------------------------------------------------------
  2003.  
  2004. fs/Makefile
  2005.  
  2006. AR =gar
  2007. AS =gas
  2008. CC =gcc
  2009. LD =gld
  2010. CFLAGS =-Wall -O -fstrength-reduce -fcombine-regs -fomit-frame-pointer \
  2011. -mstring-insns -nostdinc -I../include
  2012. CPP =gcc -E -nostdinc -I../include
  2013.  
  2014. .c.s:
  2015. $(CC) $(CFLAGS) \
  2016. -S -o $*.s $<
  2017. .c.o:
  2018. $(CC) $(CFLAGS) \
  2019. -c -o $*.o $<
  2020. .s.o:
  2021. $(AS) -o $*.o $<
  2022.  
  2023. OBJS= open.o read_write.o inode.o file_table.o buffer.o super.o \
  2024. block_dev.o char_dev.o file_dev.o stat.o exec.o pipe.o namei.o \
  2025. bitmap.o fcntl.o ioctl.o tty_ioctl.o truncate.o
  2026.  
  2027. fs.o: $(OBJS)
  2028. $(LD) -r -o fs.o $(OBJS)
  2029.  
  2030. clean:
  2031. rm -f core *.o *.a tmp_make
  2032. for i in *.c;do rm -f `basename $$i .c`.s;done
  2033.  
  2034. dep:
  2035. sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
  2036. (for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
  2037. cp tmp_make Makefile
  2038.  
  2039. ### Dependencies:
  2040. bitmap.o : bitmap.c ../include/string.h ../include/linux/sched.h \
  2041. ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
  2042. ../include/linux/mm.h ../include/linux/kernel.h
  2043. block_dev.o : block_dev.c ../include/errno.h ../include/linux/fs.h \
  2044. ../include/sys/types.h ../include/linux/kernel.h ../include/asm/segment.h
  2045. buffer.o : buffer.c ../include/linux/config.h ../include/linux/sched.h \
  2046. ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
  2047. ../include/linux/mm.h ../include/linux/kernel.h ../include/asm/system.h
  2048. char_dev.o : char_dev.c ../include/errno.h ../include/linux/sched.h \
  2049. ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
  2050. ../include/linux/mm.h ../include/linux/kernel.h
  2051. exec.o : exec.c ../include/errno.h ../include/sys/stat.h \
  2052. ../include/sys/types.h ../include/a.out.h ../include/linux/fs.h \
  2053. ../include/linux/sched.h ../include/linux/head.h ../include/linux/mm.h \
  2054. ../include/linux/kernel.h ../include/asm/segment.h
  2055. fcntl.o : fcntl.c ../include/string.h ../include/errno.h \
  2056. ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
  2057. ../include/sys/types.h ../include/linux/mm.h ../include/linux/kernel.h \
  2058. ../include/asm/segment.h ../include/fcntl.h ../include/sys/stat.h
  2059. file_dev.o : file_dev.c ../include/errno.h ../include/fcntl.h \
  2060. ../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
  2061. ../include/linux/fs.h ../include/linux/mm.h ../include/linux/kernel.h \
  2062. ../include/asm/segment.h
  2063. file_table.o : file_table.c ../include/linux/fs.h ../include/sys/types.h
  2064. inode.o : inode.c ../include/string.h ../include/linux/sched.h \
  2065. ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
  2066. ../include/linux/mm.h ../include/linux/kernel.h ../include/asm/system.h
  2067. ioctl.o : ioctl.c ../include/string.h ../include/errno.h \
  2068. ../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \
  2069. ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h
  2070. namei.o : namei.c ../include/linux/sched.h ../include/linux/head.h \
  2071. ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
  2072. ../include/linux/kernel.h ../include/asm/segment.h ../include/string.h \
  2073. ../include/fcntl.h ../include/errno.h ../include/const.h \
  2074. ../include/sys/stat.h
  2075. open.o : open.c ../include/string.h ../include/errno.h ../include/fcntl.h \
  2076. ../include/sys/types.h ../include/utime.h ../include/sys/stat.h \
  2077. ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
  2078. ../include/linux/mm.h ../include/linux/tty.h ../include/termios.h \
  2079. ../include/linux/kernel.h ../include/asm/segment.h
  2080. pipe.o : pipe.c ../include/signal.h ../include/sys/types.h \
  2081. ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
  2082. ../include/linux/mm.h ../include/asm/segment.h
  2083. read_write.o : read_write.c ../include/sys/stat.h ../include/sys/types.h \
  2084. ../include/errno.h ../include/linux/kernel.h ../include/linux/sched.h \
  2085. ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
  2086. ../include/asm/segment.h
  2087. stat.o : stat.c ../include/errno.h ../include/sys/stat.h \
  2088. ../include/sys/types.h ../include/linux/fs.h ../include/linux/sched.h \
  2089. ../include/linux/head.h ../include/linux/mm.h ../include/linux/kernel.h \
  2090. ../include/asm/segment.h
  2091. super.o : super.c ../include/linux/config.h ../include/linux/sched.h \
  2092. ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
  2093. ../include/linux/mm.h ../include/linux/kernel.h
  2094. truncate.o : truncate.c ../include/linux/sched.h ../include/linux/head.h \
  2095. ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
  2096. ../include/sys/stat.h
  2097. tty_ioctl.o : tty_ioctl.c ../include/errno.h ../include/termios.h \
  2098. ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
  2099. ../include/sys/types.h ../include/linux/mm.h ../include/linux/kernel.h \
  2100. ../include/linux/tty.h ../include/asm/segment.h ../include/asm/system.h
  2101.  
  2102. ------------------------------------------------------------------------
  2103.  
  2104. fs/namei.c
  2105.  
  2106. #include <linux/sched.h>
  2107. #include <linux/kernel.h>
  2108. #include <asm/segment.h>
  2109.  
  2110. #include <string.h>
  2111. #include <fcntl.h>
  2112. #include <errno.h>
  2113. #include <const.h>
  2114. #include <sys/stat.h>
  2115.  
  2116. #define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
  2117.  
  2118. /*
  2119. * comment out this line if you want names > NAME_LEN chars to be
  2120. * truncated. Else they will be disallowed.
  2121. */
  2122. /* #define NO_TRUNCATE */
  2123.  
  2124. #define MAY_EXEC 1
  2125. #define MAY_WRITE 2
  2126. #define MAY_READ 4
  2127.  
  2128. /*
  2129. * permission()
  2130. *
  2131. * is used to check for read/write/execute permissions on a file.
  2132. * I don't know if we should look at just the euid or both euid and
  2133. * uid, but that should be easily changed.
  2134. */
  2135. static int permission(struct m_inode * inode,int mask)
  2136. {
  2137. int mode = inode->i_mode;
  2138.  
  2139. /* special case: not even root can read/write a deleted file */
  2140. if (inode->i_dev && !inode->i_nlinks)
  2141. return 0;
  2142. if (!(current->uid && current->euid))
  2143. mode=0777;
  2144. else if (current->uid==inode->i_uid || current->euid==inode->i_uid)
  2145. mode >>= 6;
  2146. else if (current->gid==inode->i_gid || current->egid==inode->i_gid)
  2147. mode >>= 3;
  2148. return mode & mask & 0007;
  2149. }
  2150.  
  2151. /*
  2152. * ok, we cannot use strncmp, as the name is not in our data space.
  2153. * Thus we'll have to use match. No big problem. Match also makes
  2154. * some sanity tests.
  2155. *
  2156. * NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
  2157. */
  2158. static int match(int len,const char * name,struct dir_entry * de)
  2159. {
  2160. register int same __asm__("ax");
  2161.  
  2162. if (!de || !de->inode || len > NAME_LEN)
  2163. return 0;
  2164. if (len < NAME_LEN && de->name[len])
  2165. return 0;
  2166. __asm__("cld\n\t"
  2167. "fs ; repe ; cmpsb\n\t"
  2168. "setz %%al"
  2169. :"=a" (same)
  2170. :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
  2171. :"cx","di","si");
  2172. return same;
  2173. }
  2174.  
  2175. /*
  2176. * find_entry()
  2177. *
  2178. * finds and entry in the specified directory with the wanted name. It
  2179. * returns the cache buffer in which the entry was found, and the entry
  2180. * itself (as a parameter - res_dir). It does NOT read the inode of the
  2181. * entry - you'll have to do that yourself if you want to.
  2182. */
  2183. static struct buffer_head * find_entry(struct m_inode * dir,
  2184. const char * name, int namelen, struct dir_entry ** res_dir)
  2185. {
  2186. int entries;
  2187. int block,i;
  2188. struct buffer_head * bh;
  2189. struct dir_entry * de;
  2190.  
  2191. #ifdef NO_TRUNCATE
  2192. if (namelen > NAME_LEN)
  2193. return NULL;
  2194. #else
  2195. if (namelen > NAME_LEN)
  2196. namelen = NAME_LEN;
  2197. #endif
  2198. entries = dir->i_size / (sizeof (struct dir_entry));
  2199. *res_dir = NULL;
  2200. if (!namelen)
  2201. return NULL;
  2202. if (!(block = dir->i_zone[0]))
  2203. return NULL;
  2204. if (!(bh = bread(dir->i_dev,block)))
  2205. return NULL;
  2206. i = 0;
  2207. de = (struct dir_entry *) bh->b_data;
  2208. while (i < entries) {
  2209. if ((char *)de >= BLOCK_SIZE+bh->b_data) {
  2210. brelse(bh);
  2211. bh = NULL;
  2212. if (!(block = bmap(dir,i/DIR_ENTRIES_PER_BLOCK)) ||
  2213. !(bh = bread(dir->i_dev,block))) {
  2214. i += DIR_ENTRIES_PER_BLOCK;
  2215. continue;
  2216. }
  2217. de = (struct dir_entry *) bh->b_data;
  2218. }
  2219. if (match(namelen,name,de)) {
  2220. *res_dir = de;
  2221. return bh;
  2222. }
  2223. de++;
  2224. i++;
  2225. }
  2226. brelse(bh);
  2227. return NULL;
  2228. }
  2229.  
  2230. /*
  2231. * add_entry()
  2232. *
  2233. * adds a file entry to the specified directory, using the same
  2234. * semantics as find_entry(). It returns NULL if it failed.
  2235. *
  2236. * NOTE!! The inode part of 'de' is left at 0 - which means you
  2237. * may not sleep between calling this and putting something into
  2238. * the entry, as someone else might have used it while you slept.
  2239. */
  2240. static struct buffer_head * add_entry(struct m_inode * dir,
  2241. const char * name, int namelen, struct dir_entry ** res_dir)
  2242. {
  2243. int block,i;
  2244. struct buffer_head * bh;
  2245. struct dir_entry * de;
  2246.  
  2247. *res_dir = NULL;
  2248. #ifdef NO_TRUNCATE
  2249. if (namelen > NAME_LEN)
  2250. return NULL;
  2251. #else
  2252. if (namelen > NAME_LEN)
  2253. namelen = NAME_LEN;
  2254. #endif
  2255. if (!namelen)
  2256. return NULL;
  2257. if (!(block = dir->i_zone[0]))
  2258. return NULL;
  2259. if (!(bh = bread(dir->i_dev,block)))
  2260. return NULL;
  2261. i = 0;
  2262. de = (struct dir_entry *) bh->b_data;
  2263. while (1) {
  2264. if ((char *)de >= BLOCK_SIZE+bh->b_data) {
  2265. brelse(bh);
  2266. bh = NULL;
  2267. block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
  2268. if (!block)
  2269. return NULL;
  2270. if (!(bh = bread(dir->i_dev,block))) {
  2271. i += DIR_ENTRIES_PER_BLOCK;
  2272. continue;
  2273. }
  2274. de = (struct dir_entry *) bh->b_data;
  2275. }
  2276. if (i*sizeof(struct dir_entry) >= dir->i_size) {
  2277. de->inode=0;
  2278. dir->i_size = (i+1)*sizeof(struct dir_entry);
  2279. dir->i_dirt = 1;
  2280. dir->i_ctime = CURRENT_TIME;
  2281. }
  2282. if (!de->inode) {
  2283. dir->i_mtime = CURRENT_TIME;
  2284. for (i=0; i < NAME_LEN ; i++)
  2285. de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
  2286. bh->b_dirt = 1;
  2287. *res_dir = de;
  2288. return bh;
  2289. }
  2290. de++;
  2291. i++;
  2292. }
  2293. brelse(bh);
  2294. return NULL;
  2295. }
  2296.  
  2297. /*
  2298. * get_dir()
  2299. *
  2300. * Getdir traverses the pathname until it hits the topmost directory.
  2301. * It returns NULL on failure.
  2302. */
  2303. static struct m_inode * get_dir(const char * pathname)
  2304. {
  2305. char c;
  2306. const char * thisname;
  2307. struct m_inode * inode;
  2308. struct buffer_head * bh;
  2309. int namelen,inr,idev;
  2310. struct dir_entry * de;
  2311.  
  2312. if (!current->root || !current->root->i_count)
  2313. panic("No root inode");
  2314. if (!current->pwd || !current->pwd->i_count)
  2315. panic("No cwd inode");
  2316. if ((c=get_fs_byte(pathname))=='/') {
  2317. inode = current->root;
  2318. pathname++;
  2319. } else if (c)
  2320. inode = current->pwd;
  2321. else
  2322. return NULL; /* empty name is bad */
  2323. inode->i_count++;
  2324. while (1) {
  2325. thisname = pathname;
  2326. if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
  2327. iput(inode);
  2328. return NULL;
  2329. }
  2330. for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
  2331. /* nothing */ ;
  2332. if (!c)
  2333. return inode;
  2334. if (!(bh = find_entry(inode,thisname,namelen,&de))) {
  2335. iput(inode);
  2336. return NULL;
  2337. }
  2338. inr = de->inode;
  2339. idev = inode->i_dev;
  2340. brelse(bh);
  2341. iput(inode);
  2342. if (!(inode = iget(idev,inr)))
  2343. return NULL;
  2344. }
  2345. }
  2346.  
  2347. /*
  2348. * dir_namei()
  2349. *
  2350. * dir_namei() returns the inode of the directory of the
  2351. * specified name, and the name within that directory.
  2352. */
  2353. static struct m_inode * dir_namei(const char * pathname,
  2354. int * namelen, const char ** name)
  2355. {
  2356. char c;
  2357. const char * basename;
  2358. struct m_inode * dir;
  2359.  
  2360. if (!(dir = get_dir(pathname)))
  2361. return NULL;
  2362. basename = pathname;
  2363. while (c=get_fs_byte(pathname++))
  2364. if (c=='/')
  2365. basename=pathname;
  2366. *namelen = pathname-basename-1;
  2367. *name = basename;
  2368. return dir;
  2369. }
  2370.  
  2371. /*
  2372. * namei()
  2373. *
  2374. * is used by most simple commands to get the inode of a specified name.
  2375. * Open, link etc use their own routines, but this is enough for things
  2376. * like 'chmod' etc.
  2377. */
  2378. struct m_inode * namei(const char * pathname)
  2379. {
  2380. const char * basename;
  2381. int inr,dev,namelen;
  2382. struct m_inode * dir;
  2383. struct buffer_head * bh;
  2384. struct dir_entry * de;
  2385.  
  2386. if (!(dir = dir_namei(pathname,&namelen,&basename)))
  2387. return NULL;
  2388. if (!namelen) /* special case: '/usr/' etc */
  2389. return dir;
  2390. bh = find_entry(dir,basename,namelen,&de);
  2391. if (!bh) {
  2392. iput(dir);
  2393. return NULL;
  2394. }
  2395. inr = de->inode;
  2396. dev = dir->i_dev;
  2397. brelse(bh);
  2398. iput(dir);
  2399. dir=iget(dev,inr);
  2400. if (dir) {
  2401. dir->i_atime=CURRENT_TIME;
  2402. dir->i_dirt=1;
  2403. }
  2404. return dir;
  2405. }
  2406.  
  2407. /*
  2408. * open_namei()
  2409. *
  2410. * namei for open - this is in fact almost the whole open-routine.
  2411. */
  2412. int open_namei(const char * pathname, int flag, int mode,
  2413. struct m_inode ** res_inode)
  2414. {
  2415. const char * basename;
  2416. int inr,dev,namelen;
  2417. struct m_inode * dir, *inode;
  2418. struct buffer_head * bh;
  2419. struct dir_entry * de;
  2420.  
  2421. if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
  2422. flag |= O_WRONLY;
  2423. mode &= 0777 & ~current->umask;
  2424. mode |= I_REGULAR;
  2425. if (!(dir = dir_namei(pathname,&namelen,&basename)))
  2426. return -ENOENT;
  2427. if (!namelen) { /* special case: '/usr/' etc */
  2428. if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
  2429. *res_inode=dir;
  2430. return 0;
  2431. }
  2432. iput(dir);
  2433. return -EISDIR;
  2434. }
  2435. bh = find_entry(dir,basename,namelen,&de);
  2436. if (!bh) {
  2437. if (!(flag & O_CREAT)) {
  2438. iput(dir);
  2439. return -ENOENT;
  2440. }
  2441. if (!permission(dir,MAY_WRITE)) {
  2442. iput(dir);
  2443. return -EACCES;
  2444. }
  2445. inode = new_inode(dir->i_dev);
  2446. if (!inode) {
  2447. iput(dir);
  2448. return -ENOSPC;
  2449. }
  2450. inode->i_mode = mode;
  2451. inode->i_dirt = 1;
  2452. bh = add_entry(dir,basename,namelen,&de);
  2453. if (!bh) {
  2454. inode->i_nlinks--;
  2455. iput(inode);
  2456. iput(dir);
  2457. return -ENOSPC;
  2458. }
  2459. de->inode = inode->i_num;
  2460. bh->b_dirt = 1;
  2461. brelse(bh);
  2462. iput(dir);
  2463. *res_inode = inode;
  2464. return 0;
  2465. }
  2466. inr = de->inode;
  2467. dev = dir->i_dev;
  2468. brelse(bh);
  2469. iput(dir);
  2470. if (flag & O_EXCL)
  2471. return -EEXIST;
  2472. if (!(inode=iget(dev,inr)))
  2473. return -EACCES;
  2474. if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
  2475. permission(inode,ACC_MODE(flag))!=ACC_MODE(flag)) {
  2476. iput(inode);
  2477. return -EPERM;
  2478. }
  2479. inode->i_atime = CURRENT_TIME;
  2480. if (flag & O_TRUNC)
  2481. truncate(inode);
  2482. *res_inode = inode;
  2483. return 0;
  2484. }
  2485.  
  2486. int sys_mkdir(const char * pathname, int mode)
  2487. {
  2488. const char * basename;
  2489. int namelen;
  2490. struct m_inode * dir, * inode;
  2491. struct buffer_head * bh, *dir_block;
  2492. struct dir_entry * de;
  2493.  
  2494. if (current->euid && current->uid)
  2495. return -EPERM;
  2496. if (!(dir = dir_namei(pathname,&namelen,&basename)))
  2497. return -ENOENT;
  2498. if (!namelen) {
  2499. iput(dir);
  2500. return -ENOENT;
  2501. }
  2502. if (!permission(dir,MAY_WRITE)) {
  2503. iput(dir);
  2504. return -EPERM;
  2505. }
  2506. bh = find_entry(dir,basename,namelen,&de);
  2507. if (bh) {
  2508. brelse(bh);
  2509. iput(dir);
  2510. return -EEXIST;
  2511. }
  2512. inode = new_inode(dir->i_dev);
  2513. if (!inode) {
  2514. iput(dir);
  2515. return -ENOSPC;
  2516. }
  2517. inode->i_size = 32;
  2518. inode->i_dirt = 1;
  2519. inode->i_mtime = inode->i_atime = CURRENT_TIME;
  2520. if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
  2521. iput(dir);
  2522. inode->i_nlinks--;
  2523. iput(inode);
  2524. return -ENOSPC;
  2525. }
  2526. inode->i_dirt = 1;
  2527. if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
  2528. iput(dir);
  2529. free_block(inode->i_dev,inode->i_zone[0]);
  2530. inode->i_nlinks--;
  2531. iput(inode);
  2532. return -ERROR;
  2533. }
  2534. de = (struct dir_entry *) dir_block->b_data;
  2535. de->inode=inode->i_num;
  2536. strcpy(de->name,".");
  2537. de++;
  2538. de->inode = dir->i_num;
  2539. strcpy(de->name,"..");
  2540. inode->i_nlinks = 2;
  2541. dir_block->b_dirt = 1;
  2542. brelse(dir_block);
  2543. inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
  2544. inode->i_dirt = 1;
  2545. bh = add_entry(dir,basename,namelen,&de);
  2546. if (!bh) {
  2547. iput(dir);
  2548. free_block(inode->i_dev,inode->i_zone[0]);
  2549. inode->i_nlinks=0;
  2550. iput(inode);
  2551. return -ENOSPC;
  2552. }
  2553. de->inode = inode->i_num;
  2554. bh->b_dirt = 1;
  2555. dir->i_nlinks++;
  2556. dir->i_dirt = 1;
  2557. iput(dir);
  2558. iput(inode);
  2559. brelse(bh);
  2560. return 0;
  2561. }
  2562.  
  2563. /*
  2564. * routine to check that the specified directory is empty (for rmdir)
  2565. */
  2566. static int empty_dir(struct m_inode * inode)
  2567. {
  2568. int nr,block;
  2569. int len;
  2570. struct buffer_head * bh;
  2571. struct dir_entry * de;
  2572.  
  2573. len = inode->i_size / sizeof (struct dir_entry);
  2574. if (len<2 || !inode->i_zone[0] ||
  2575. !(bh=bread(inode->i_dev,inode->i_zone[0]))) {
  2576. printk("warning - bad directory on dev %04x\n",inode->i_dev);
  2577. return 0;
  2578. }
  2579. de = (struct dir_entry *) bh->b_data;
  2580. if (de[0].inode != inode->i_num || !de[1].inode ||
  2581. strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
  2582. printk("warning - bad directory on dev %04x\n",inode->i_dev);
  2583. return 0;
  2584. }
  2585. nr = 2;
  2586. de += 2;
  2587. while (nr<len) {
  2588. if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
  2589. brelse(bh);
  2590. block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
  2591. if (!block) {
  2592. nr += DIR_ENTRIES_PER_BLOCK;
  2593. continue;
  2594. }
  2595. if (!(bh=bread(inode->i_dev,block)))
  2596. return 0;
  2597. de = (struct dir_entry *) bh->b_data;
  2598. }
  2599. if (de->inode) {
  2600. brelse(bh);
  2601. return 0;
  2602. }
  2603. de++;
  2604. nr++;
  2605. }
  2606. brelse(bh);
  2607. return 1;
  2608. }
  2609.  
  2610. int sys_rmdir(const char * name)
  2611. {
  2612. const char * basename;
  2613. int namelen;
  2614. struct m_inode * dir, * inode;
  2615. struct buffer_head * bh;
  2616. struct dir_entry * de;
  2617.  
  2618. if (current->euid && current->uid)
  2619. return -EPERM;
  2620. if (!(dir = dir_namei(name,&namelen,&basename)))
  2621. return -ENOENT;
  2622. if (!namelen) {
  2623. iput(dir);
  2624. return -ENOENT;
  2625. }
  2626. bh = find_entry(dir,basename,namelen,&de);
  2627. if (!bh) {
  2628. iput(dir);
  2629. return -ENOENT;
  2630. }
  2631. if (!permission(dir,MAY_WRITE)) {
  2632. iput(dir);
  2633. brelse(bh);
  2634. return -EPERM;
  2635. }
  2636. if (!(inode = iget(dir->i_dev, de->inode))) {
  2637. iput(dir);
  2638. brelse(bh);
  2639. return -EPERM;
  2640. }
  2641. if (inode == dir) { /* we may not delete ".", but "../dir" is ok */
  2642. iput(inode);
  2643. iput(dir);
  2644. brelse(bh);
  2645. return -EPERM;
  2646. }
  2647. if (!S_ISDIR(inode->i_mode)) {
  2648. iput(inode);
  2649. iput(dir);
  2650. brelse(bh);
  2651. return -ENOTDIR;
  2652. }
  2653. if (!empty_dir(inode)) {
  2654. iput(inode);
  2655. iput(dir);
  2656. brelse(bh);
  2657. return -ENOTEMPTY;
  2658. }
  2659. if (inode->i_nlinks != 2)
  2660. printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
  2661. de->inode = 0;
  2662. bh->b_dirt = 1;
  2663. brelse(bh);
  2664. inode->i_nlinks=0;
  2665. inode->i_dirt=1;
  2666. dir->i_nlinks--;
  2667. dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  2668. dir->i_dirt=1;
  2669. iput(dir);
  2670. iput(inode);
  2671. return 0;
  2672. }
  2673.  
  2674. int sys_unlink(const char * name)
  2675. {
  2676. const char * basename;
  2677. int namelen;
  2678. struct m_inode * dir, * inode;
  2679. struct buffer_head * bh;
  2680. struct dir_entry * de;
  2681.  
  2682. if (!(dir = dir_namei(name,&namelen,&basename)))
  2683. return -ENOENT;
  2684. if (!namelen) {
  2685. iput(dir);
  2686. return -ENOENT;
  2687. }
  2688. if (!permission(dir,MAY_WRITE)) {
  2689. iput(dir);
  2690. return -EPERM;
  2691. }
  2692. bh = find_entry(dir,basename,namelen,&de);
  2693. if (!bh) {
  2694. iput(dir);
  2695. return -ENOENT;
  2696. }
  2697. inode = iget(dir->i_dev, de->inode);
  2698. if (!inode) {
  2699. printk("iget failed in delete (%04x:%d)",dir->i_dev,de->inode);
  2700. iput(dir);
  2701. brelse(bh);
  2702. return -ENOENT;
  2703. }
  2704. if (!S_ISREG(inode->i_mode)) {
  2705. iput(inode);
  2706. iput(dir);
  2707. brelse(bh);
  2708. return -EPERM;
  2709. }
  2710. if (!inode->i_nlinks) {
  2711. printk("Deleting nonexistent file (%04x:%d), %d\n",
  2712. inode->i_dev,inode->i_num,inode->i_nlinks);
  2713. inode->i_nlinks=1;
  2714. }
  2715. de->inode = 0;
  2716. bh->b_dirt = 1;
  2717. brelse(bh);
  2718. inode->i_nlinks--;
  2719. inode->i_dirt = 1;
  2720. inode->i_ctime = CURRENT_TIME;
  2721. iput(inode);
  2722. iput(dir);
  2723. return 0;
  2724. }
  2725.  
  2726. int sys_link(const char * oldname, const char * newname)
  2727. {
  2728. struct dir_entry * de;
  2729. struct m_inode * oldinode, * dir;
  2730. struct buffer_head * bh;
  2731. const char * basename;
  2732. int namelen;
  2733.  
  2734. oldinode=namei(oldname);
  2735. if (!oldinode)
  2736. return -ENOENT;
  2737. if (!S_ISREG(oldinode->i_mode)) {
  2738. iput(oldinode);
  2739. return -EPERM;
  2740. }
  2741. dir = dir_namei(newname,&namelen,&basename);
  2742. if (!dir) {
  2743. iput(oldinode);
  2744. return -EACCES;
  2745. }
  2746. if (!namelen) {
  2747. iput(oldinode);
  2748. iput(dir);
  2749. return -EPERM;
  2750. }
  2751. if (dir->i_dev != oldinode->i_dev) {
  2752. iput(dir);
  2753. iput(oldinode);
  2754. return -EXDEV;
  2755. }
  2756. if (!permission(dir,MAY_WRITE)) {
  2757. iput(dir);
  2758. iput(oldinode);
  2759. return -EACCES;
  2760. }
  2761. bh = find_entry(dir,basename,namelen,&de);
  2762. if (bh) {
  2763. brelse(bh);
  2764. iput(dir);
  2765. iput(oldinode);
  2766. return -EEXIST;
  2767. }
  2768. bh = add_entry(dir,basename,namelen,&de);
  2769. if (!bh) {
  2770. iput(dir);
  2771. iput(oldinode);
  2772. return -ENOSPC;
  2773. }
  2774. de->inode = oldinode->i_num;
  2775. bh->b_dirt = 1;
  2776. brelse(bh);
  2777. iput(dir);
  2778. oldinode->i_nlinks++;
  2779. oldinode->i_ctime = CURRENT_TIME;
  2780. oldinode->i_dirt = 1;
  2781. iput(oldinode);
  2782. return 0;
  2783. }
  2784.  
  2785. ------------------------------------------------------------------------
  2786.  
  2787. fs/open.c
  2788.  
  2789. #include <string.h>
  2790. #include <errno.h>
  2791. #include <fcntl.h>
  2792. #include <sys/types.h>
  2793. #include <utime.h>
  2794. #include <sys/stat.h>
  2795.  
  2796. #include <linux/sched.h>
  2797. #include <linux/tty.h>
  2798. #include <linux/kernel.h>
  2799. #include <asm/segment.h>
  2800.  
  2801. int sys_utime(char * filename, struct utimbuf * times)
  2802. {
  2803. struct m_inode * inode;
  2804. long actime,modtime;
  2805.  
  2806. if (!(inode=namei(filename)))
  2807. return -ENOENT;
  2808. if (times) {
  2809. actime = get_fs_long((unsigned long *) &times->actime);
  2810. modtime = get_fs_long((unsigned long *) &times->modtime);
  2811. } else
  2812. actime = modtime = CURRENT_TIME;
  2813. inode->i_atime = actime;
  2814. inode->i_mtime = modtime;
  2815. inode->i_dirt = 1;
  2816. iput(inode);
  2817. return 0;
  2818. }
  2819.  
  2820. int sys_access(const char * filename,int mode)
  2821. {
  2822. struct m_inode * inode;
  2823. int res;
  2824.  
  2825. mode &= 0007;
  2826. if (!(inode=namei(filename)))
  2827. return -EACCES;
  2828. res = inode->i_mode & 0777;
  2829. iput(inode);
  2830. if (!(current->euid && current->uid))
  2831. if (res & 0111)
  2832. res = 0777;
  2833. else
  2834. res = 0666;
  2835. if (current->euid == inode->i_uid)
  2836. res >>= 6;
  2837. else if (current->egid == inode->i_gid)
  2838. res >>= 6;
  2839. if ((res & 0007 & mode) == mode)
  2840. return 0;
  2841. return -EACCES;
  2842. }
  2843.  
  2844. int sys_chdir(const char * filename)
  2845. {
  2846. struct m_inode * inode;
  2847.  
  2848. if (!(inode = namei(filename)))
  2849. return -ENOENT;
  2850. if (!S_ISDIR(inode->i_mode)) {
  2851. iput(inode);
  2852. return -ENOTDIR;
  2853. }
  2854. iput(current->pwd);
  2855. current->pwd = inode;
  2856. return (0);
  2857. }
  2858.  
  2859. int sys_chroot(const char * filename)
  2860. {
  2861. struct m_inode * inode;
  2862.  
  2863. if (!(inode=namei(filename)))
  2864. return -ENOENT;
  2865. if (!S_ISDIR(inode->i_mode)) {
  2866. iput(inode);
  2867. return -ENOTDIR;
  2868. }
  2869. iput(current->root);
  2870. current->root = inode;
  2871. return (0);
  2872. }
  2873.  
  2874. int sys_chmod(const char * filename,int mode)
  2875. {
  2876. struct m_inode * inode;
  2877.  
  2878. if (!(inode=namei(filename)))
  2879. return -ENOENT;
  2880. if (current->uid && current->euid)
  2881. if (current->uid!=inode->i_uid && current->euid!=inode->i_uid) {
  2882. iput(inode);
  2883. return -EACCES;
  2884. } else
  2885. mode = (mode & 0777) | (inode->i_mode & 07000);
  2886. inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
  2887. inode->i_dirt = 1;
  2888. iput(inode);
  2889. return 0;
  2890. }
  2891.  
  2892. int sys_chown(const char * filename,int uid,int gid)
  2893. {
  2894. struct m_inode * inode;
  2895.  
  2896. if (!(inode=namei(filename)))
  2897. return -ENOENT;
  2898. if (current->uid && current->euid) {
  2899. iput(inode);
  2900. return -EACCES;
  2901. }
  2902. inode->i_uid=uid;
  2903. inode->i_gid=gid;
  2904. inode->i_dirt=1;
  2905. iput(inode);
  2906. return 0;
  2907. }
  2908.  
  2909. int sys_open(const char * filename,int flag,int mode)
  2910. {
  2911. struct m_inode * inode;
  2912. struct file * f;
  2913. int i,fd;
  2914.  
  2915. mode &= 0777 & ~current->umask;
  2916. for(fd=0 ; fd<NR_OPEN ; fd++)
  2917. if (!current->filp[fd])
  2918. break;
  2919. if (fd>=NR_OPEN)
  2920. return -EINVAL;
  2921. current->close_on_exec &= ~(1<<fd);
  2922. f=0+file_table;
  2923. for (i=0 ; i<NR_FILE ; i++,f++)
  2924. if (!f->f_count) break;
  2925. if (i>=NR_FILE)
  2926. return -EINVAL;
  2927. (current->filp[fd]=f)->f_count++;
  2928. if ((i=open_namei(filename,flag,mode,&inode))<0) {
  2929. current->filp[fd]=NULL;
  2930. f->f_count=0;
  2931. return i;
  2932. }
  2933. /* ttys are somewhat special (ttyxx major==4, tty major==5) */
  2934. if (S_ISCHR(inode->i_mode))
  2935. if (MAJOR(inode->i_zone[0])==4) {
  2936. if (current->leader && current->tty<0) {
  2937. current->tty = MINOR(inode->i_zone[0]);
  2938. tty_table[current->tty].pgrp = current->pgrp;
  2939. }
  2940. } else if (MAJOR(inode->i_zone[0])==5)
  2941. if (current->tty<0) {
  2942. iput(inode);
  2943. current->filp[fd]=NULL;
  2944. f->f_count=0;
  2945. return -EPERM;
  2946. }
  2947. f->f_mode = inode->i_mode;
  2948. f->f_flags = flag;
  2949. f->f_count = 1;
  2950. f->f_inode = inode;
  2951. f->f_pos = 0;
  2952. return (fd);
  2953. }
  2954.  
  2955. int sys_creat(const char * pathname, int mode)
  2956. {
  2957. return sys_open(pathname, O_CREAT | O_TRUNC, mode);
  2958. }
  2959.  
  2960. int sys_close(unsigned int fd)
  2961. {
  2962. struct file * filp;
  2963.  
  2964. if (fd >= NR_OPEN)
  2965. return -EINVAL;
  2966. current->close_on_exec &= ~(1<<fd);
  2967. if (!(filp = current->filp[fd]))
  2968. return -EINVAL;
  2969. current->filp[fd] = NULL;
  2970. if (filp->f_count == 0)
  2971. panic("Close: file count is 0");
  2972. if (--filp->f_count)
  2973. return (0);
  2974. iput(filp->f_inode);
  2975. return (0);
  2976. }
  2977.  
  2978. ------------------------------------------------------------------------
  2979.  
  2980. fs/pipe.c
  2981.  
  2982. #include <signal.h>
  2983.  
  2984. #include <linux/sched.h>
  2985. #include <linux/mm.h> /* for get_free_page */
  2986. #include <asm/segment.h>
  2987.  
  2988. int read_pipe(struct m_inode * inode, char * buf, int count)
  2989. {
  2990. char * b=buf;
  2991.  
  2992. while (PIPE_EMPTY(*inode)) {
  2993. wake_up(&inode->i_wait);
  2994. if (inode->i_count != 2) /* are there any writers left? */
  2995. return 0;
  2996. sleep_on(&inode->i_wait);
  2997. }
  2998. while (count>0 && !(PIPE_EMPTY(*inode))) {
  2999. count --;
  3000. put_fs_byte(((char *)inode->i_size)[PIPE_TAIL(*inode)],b++);
  3001. INC_PIPE( PIPE_TAIL(*inode) );
  3002. }
  3003. wake_up(&inode->i_wait);
  3004. return b-buf;
  3005. }
  3006.  
  3007. int write_pipe(struct m_inode * inode, char * buf, int count)
  3008. {
  3009. char * b=buf;
  3010.  
  3011. wake_up(&inode->i_wait);
  3012. if (inode->i_count != 2) { /* no readers */
  3013. current->signal |= (1<<(SIGPIPE-1));
  3014. return -1;
  3015. }
  3016. while (count-->0) {
  3017. while (PIPE_FULL(*inode)) {
  3018. wake_up(&inode->i_wait);
  3019. if (inode->i_count != 2) {
  3020. current->signal |= (1<<(SIGPIPE-1));
  3021. return b-buf;
  3022. }
  3023. sleep_on(&inode->i_wait);
  3024. }
  3025. ((char *)inode->i_size)[PIPE_HEAD(*inode)] = get_fs_byte(b++);
  3026. INC_PIPE( PIPE_HEAD(*inode) );
  3027. wake_up(&inode->i_wait);
  3028. }
  3029. wake_up(&inode->i_wait);
  3030. return b-buf;
  3031. }
  3032.  
  3033. int sys_pipe(unsigned long * fildes)
  3034. {
  3035. struct m_inode * inode;
  3036. struct file * f[2];
  3037. int fd[2];
  3038. int i,j;
  3039.  
  3040. j=0;
  3041. for(i=0;j<2 && i<NR_FILE;i++)
  3042. if (!file_table[i].f_count)
  3043. (f[j++]=i+file_table)->f_count++;
  3044. if (j==1)
  3045. f[0]->f_count=0;
  3046. if (j<2)
  3047. return -1;
  3048. j=0;
  3049. for(i=0;j<2 && i<NR_OPEN;i++)
  3050. if (!current->filp[i]) {
  3051. current->filp[ fd[j]=i ] = f[j];
  3052. j++;
  3053. }
  3054. if (j==1)
  3055. current->filp[fd[0]]=NULL;
  3056. if (j<2) {
  3057. f[0]->f_count=f[1]->f_count=0;
  3058. return -1;
  3059. }
  3060. if (!(inode=get_pipe_inode())) {
  3061. current->filp[fd[0]] =
  3062. current->filp[fd[1]] = NULL;
  3063. f[0]->f_count = f[1]->f_count = 0;
  3064. return -1;
  3065. }
  3066. f[0]->f_inode = f[1]->f_inode = inode;
  3067. f[0]->f_pos = f[1]->f_pos = 0;
  3068. f[0]->f_mode = 1; /* read */
  3069. f[1]->f_mode = 2; /* write */
  3070. put_fs_long(fd[0],0+fildes);
  3071. put_fs_long(fd[1],1+fildes);
  3072. return 0;
  3073. }
  3074.  
  3075. ------------------------------------------------------------------------
  3076.  
  3077. fs/read_write.c
  3078.  
  3079. #include <sys/stat.h>
  3080. #include <errno.h>
  3081. #include <sys/types.h>
  3082.  
  3083. #include <linux/kernel.h>
  3084. #include <linux/sched.h>
  3085. #include <asm/segment.h>
  3086.  
  3087. extern int rw_char(int rw,int dev, char * buf, int count);
  3088. extern int read_pipe(struct m_inode * inode, char * buf, int count);
  3089. extern int write_pipe(struct m_inode * inode, char * buf, int count);
  3090. extern int block_read(int dev, off_t * pos, char * buf, int count);
  3091. extern int block_write(int dev, off_t * pos, char * buf, int count);
  3092. extern int file_read(struct m_inode * inode, struct file * filp,
  3093. char * buf, int count);
  3094. extern int file_write(struct m_inode * inode, struct file * filp,
  3095. char * buf, int count);
  3096.  
  3097. int sys_lseek(unsigned int fd,off_t offset, int origin)
  3098. {
  3099. struct file * file;
  3100. int tmp;
  3101.  
  3102. if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode)
  3103. || !IS_BLOCKDEV(MAJOR(file->f_inode->i_dev)))
  3104. return -EBADF;
  3105. if (file->f_inode->i_pipe)
  3106. return -ESPIPE;
  3107. switch (origin) {
  3108. case 0:
  3109. if (offset<0) return -EINVAL;
  3110. file->f_pos=offset;
  3111. break;
  3112. case 1:
  3113. if (file->f_pos+offset<0) return -EINVAL;
  3114. file->f_pos += offset;
  3115. break;
  3116. case 2:
  3117. if ((tmp=file->f_inode->i_size+offset) < 0)
  3118. return -EINVAL;
  3119. file->f_pos = tmp;
  3120. break;
  3121. default:
  3122. return -EINVAL;
  3123. }
  3124. return file->f_pos;
  3125. }
  3126.  
  3127. int sys_read(unsigned int fd,char * buf,int count)
  3128. {
  3129. struct file * file;
  3130. struct m_inode * inode;
  3131.  
  3132. if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd]))
  3133. return -EINVAL;
  3134. if (!count)
  3135. return 0;
  3136. verify_area(buf,count);
  3137. inode = file->f_inode;
  3138. if (inode->i_pipe)
  3139. return (file->f_mode&1)?read_pipe(inode,buf,count):-1;
  3140. if (S_ISCHR(inode->i_mode))
  3141. return rw_char(READ,inode->i_zone[0],buf,count);
  3142. if (S_ISBLK(inode->i_mode))
  3143. return block_read(inode->i_zone[0],&file->f_pos,buf,count);
  3144. if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {
  3145. if (count+file->f_pos > inode->i_size)
  3146. count = inode->i_size - file->f_pos;
  3147. if (count<=0)
  3148. return 0;
  3149. return file_read(inode,file,buf,count);
  3150. }
  3151. printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
  3152. return -EINVAL;
  3153. }
  3154.  
  3155. int sys_write(unsigned int fd,char * buf,int count)
  3156. {
  3157. struct file * file;
  3158. struct m_inode * inode;
  3159.  
  3160. if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd]))
  3161. return -EINVAL;
  3162. if (!count)
  3163. return 0;
  3164. inode=file->f_inode;
  3165. if (inode->i_pipe)
  3166. return (file->f_mode&2)?write_pipe(inode,buf,count):-1;
  3167. if (S_ISCHR(inode->i_mode))
  3168. return rw_char(WRITE,inode->i_zone[0],buf,count);
  3169. if (S_ISBLK(inode->i_mode))
  3170. return block_write(inode->i_zone[0],&file->f_pos,buf,count);
  3171. if (S_ISREG(inode->i_mode))
  3172. return file_write(inode,file,buf,count);
  3173. printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
  3174. return -EINVAL;
  3175. }
  3176.  
  3177. ------------------------------------------------------------------------
  3178.  
  3179. fs/stat.c
  3180.  
  3181. #include <errno.h>
  3182. #include <sys/stat.h>
  3183.  
  3184. #include <linux/fs.h>
  3185. #include <linux/sched.h>
  3186. #include <linux/kernel.h>
  3187. #include <asm/segment.h>
  3188.  
  3189. static int cp_stat(struct m_inode * inode, struct stat * statbuf)
  3190. {
  3191. struct stat tmp;
  3192. int i;
  3193.  
  3194. verify_area(statbuf,sizeof (* statbuf));
  3195. tmp.st_dev = inode->i_dev;
  3196. tmp.st_ino = inode->i_num;
  3197. tmp.st_mode = inode->i_mode;
  3198. tmp.st_nlink = inode->i_nlinks;
  3199. tmp.st_uid = inode->i_uid;
  3200. tmp.st_gid = inode->i_gid;
  3201. tmp.st_rdev = inode->i_zone[0];
  3202. tmp.st_size = inode->i_size;
  3203. tmp.st_atime = inode->i_atime;
  3204. tmp.st_mtime = inode->i_mtime;
  3205. tmp.st_ctime = inode->i_ctime;
  3206. for (i=0 ; i<sizeof (tmp) ; i++)
  3207. put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]);
  3208. return (0);
  3209. }
  3210.  
  3211. int sys_stat(char * filename, struct stat * statbuf)
  3212. {
  3213. int i;
  3214. struct m_inode * inode;
  3215.  
  3216. if (!(inode=namei(filename)))
  3217. return -ENOENT;
  3218. i=cp_stat(inode,statbuf);
  3219. iput(inode);
  3220. return i;
  3221. }
  3222.  
  3223. int sys_fstat(unsigned int fd, struct stat * statbuf)
  3224. {
  3225. struct file * f;
  3226. struct m_inode * inode;
  3227.  
  3228. if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
  3229. return -ENOENT;
  3230. return cp_stat(inode,statbuf);
  3231. }
  3232.  
  3233. ------------------------------------------------------------------------
  3234.  
  3235. fs/super.c
  3236.  
  3237. /*
  3238. * super.c contains code to handle the super-block tables.
  3239. */
  3240. #include <linux/config.h>
  3241. #include <linux/sched.h>
  3242. #include <linux/kernel.h>
  3243.  
  3244. /* set_bit uses setb, as gas doesn't recognize setc */
  3245. #define set_bit(bitnr,addr) ({ \
  3246. register int __res __asm__("ax"); \
  3247. __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
  3248. __res; })
  3249.  
  3250. struct super_block super_block[NR_SUPER];
  3251.  
  3252. struct super_block * do_mount(int dev)
  3253. {
  3254. struct super_block * p;
  3255. struct buffer_head * bh;
  3256. int i,block;
  3257.  
  3258. for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++ )
  3259. if (!(p->s_dev))
  3260. break;
  3261. p->s_dev = -1; /* mark it in use */
  3262. if (p >= &super_block[NR_SUPER])
  3263. return NULL;
  3264. if (!(bh = bread(dev,1)))
  3265. return NULL;
  3266. *p = *((struct super_block *) bh->b_data);
  3267. brelse(bh);
  3268. if (p->s_magic != SUPER_MAGIC) {
  3269. p->s_dev = 0;
  3270. return NULL;
  3271. }
  3272. for (i=0;i<I_MAP_SLOTS;i++)
  3273. p->s_imap[i] = NULL;
  3274. for (i=0;i<Z_MAP_SLOTS;i++)
  3275. p->s_zmap[i] = NULL;
  3276. block=2;
  3277. for (i=0 ; i < p->s_imap_blocks ; i++)
  3278. if (p->s_imap[i]=bread(dev,block))
  3279. block++;
  3280. else
  3281. break;
  3282. for (i=0 ; i < p->s_zmap_blocks ; i++)
  3283. if (p->s_zmap[i]=bread(dev,block))
  3284. block++;
  3285. else
  3286. break;
  3287. if (block != 2+p->s_imap_blocks+p->s_zmap_blocks) {
  3288. for(i=0;i<I_MAP_SLOTS;i++)
  3289. brelse(p->s_imap[i]);
  3290. for(i=0;i<Z_MAP_SLOTS;i++)
  3291. brelse(p->s_zmap[i]);
  3292. p->s_dev=0;
  3293. return NULL;
  3294. }
  3295. p->s_imap[0]->b_data[0] |= 1;
  3296. p->s_zmap[0]->b_data[0] |= 1;
  3297. p->s_dev = dev;
  3298. p->s_isup = NULL;
  3299. p->s_imount = NULL;
  3300. p->s_time = 0;
  3301. p->s_rd_only = 0;
  3302. p->s_dirt = 0;
  3303. return p;
  3304. }
  3305.  
  3306. void mount_root(void)
  3307. {
  3308. int i,free;
  3309. struct super_block * p;
  3310. struct m_inode * mi;
  3311.  
  3312. if (32 != sizeof (struct d_inode))
  3313. panic("bad i-node size");
  3314. for(i=0;i<NR_FILE;i++)
  3315. file_table[i].f_count=0;
  3316. for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++)
  3317. p->s_dev = 0;
  3318. if (!(p=do_mount(ROOT_DEV)))
  3319. panic("Unable to mount root");
  3320. if (!(mi=iget(ROOT_DEV,1)))
  3321. panic("Unable to read root i-node");
  3322. mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
  3323. p->s_isup = p->s_imount = mi;
  3324. current->pwd = mi;
  3325. current->root = mi;
  3326. free=0;
  3327. i=p->s_nzones;
  3328. while (-- i >= 0)
  3329. if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
  3330. free++;
  3331. printk("%d/%d free blocks\n\r",free,p->s_nzones);
  3332. free=0;
  3333. i=p->s_ninodes+1;
  3334. while (-- i >= 0)
  3335. if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
  3336. free++;
  3337. printk("%d/%d free inodes\n\r",free,p->s_ninodes);
  3338. }
  3339.  
  3340. ------------------------------------------------------------------------
  3341.  
  3342. fs/truncate.c
  3343.  
  3344. #include <linux/sched.h>
  3345.  
  3346. #include <sys/stat.h>
  3347.  
  3348. static void free_ind(int dev,int block)
  3349. {
  3350. struct buffer_head * bh;
  3351. unsigned short * p;
  3352. int i;
  3353.  
  3354. if (!block)
  3355. return;
  3356. if (bh=bread(dev,block)) {
  3357. p = (unsigned short *) bh->b_data;
  3358. for (i=0;i<512;i++,p++)
  3359. if (*p)
  3360. free_block(dev,*p);
  3361. brelse(bh);
  3362. }
  3363. free_block(dev,block);
  3364. }
  3365.  
  3366. static void free_dind(int dev,int block)
  3367. {
  3368. struct buffer_head * bh;
  3369. unsigned short * p;
  3370. int i;
  3371.  
  3372. if (!block)
  3373. return;
  3374. if (bh=bread(dev,block)) {
  3375. p = (unsigned short *) bh->b_data;
  3376. for (i=0;i<512;i++,p++)
  3377. if (*p)
  3378. free_ind(dev,*p);
  3379. brelse(bh);
  3380. }
  3381. free_block(dev,block);
  3382. }
  3383.  
  3384. void truncate(struct m_inode * inode)
  3385. {
  3386. int i;
  3387.  
  3388. if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
  3389. return;
  3390. for (i=0;i<7;i++)
  3391. if (inode->i_zone[i]) {
  3392. free_block(inode->i_dev,inode->i_zone[i]);
  3393. inode->i_zone[i]=0;
  3394. }
  3395. free_ind(inode->i_dev,inode->i_zone[7]);
  3396. free_dind(inode->i_dev,inode->i_zone[8]);
  3397. inode->i_zone[7] = inode->i_zone[8] = 0;
  3398. inode->i_size = 0;
  3399. inode->i_dirt = 1;
  3400. inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  3401. }
  3402.  
  3403.  
  3404. ------------------------------------------------------------------------
  3405.  
  3406. fs/tty_ioctl.c
  3407.  
  3408. #include <errno.h>
  3409. #include <termios.h>
  3410.  
  3411. #include <linux/sched.h>
  3412. #include <linux/kernel.h>
  3413. #include <linux/tty.h>
  3414.  
  3415. #include <asm/segment.h>
  3416. #include <asm/system.h>
  3417.  
  3418. static void flush(struct tty_queue * queue)
  3419. {
  3420. cli();
  3421. queue->head = queue->tail;
  3422. sti();
  3423. }
  3424.  
  3425. static void wait_until_sent(struct tty_struct * tty)
  3426. {
  3427. /* do nothing - not implemented */
  3428. }
  3429.  
  3430. static void send_break(struct tty_struct * tty)
  3431. {
  3432. /* do nothing - not implemented */
  3433. }
  3434.  
  3435. static int get_termios(struct tty_struct * tty, struct termios * termios)
  3436. {
  3437. int i;
  3438.  
  3439. verify_area(termios, sizeof (*termios));
  3440. for (i=0 ; i< (sizeof (*termios)) ; i++)
  3441. put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );
  3442. return 0;
  3443. }
  3444.  
  3445. static int set_termios(struct tty_struct * tty, struct termios * termios)
  3446. {
  3447. int i;
  3448.  
  3449. for (i=0 ; i< (sizeof (*termios)) ; i++)
  3450. ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
  3451. return 0;
  3452. }
  3453.  
  3454. static int get_termio(struct tty_struct * tty, struct termio * termio)
  3455. {
  3456. int i;
  3457. struct termio tmp_termio;
  3458.  
  3459. verify_area(termio, sizeof (*termio));
  3460. tmp_termio.c_iflag = tty->termios.c_iflag;
  3461. tmp_termio.c_oflag = tty->termios.c_oflag;
  3462. tmp_termio.c_cflag = tty->termios.c_cflag;
  3463. tmp_termio.c_lflag = tty->termios.c_lflag;
  3464. tmp_termio.c_line = tty->termios.c_line;
  3465. for(i=0 ; i < NCC ; i++)
  3466. tmp_termio.c_cc[i] = tty->termios.c_cc[i];
  3467. for (i=0 ; i< (sizeof (*termio)) ; i++)
  3468. put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
  3469. return 0;
  3470. }
  3471.  
  3472. static int set_termio(struct tty_struct * tty, struct termio * termio)
  3473. {
  3474. int i;
  3475. struct termio tmp_termio;
  3476.  
  3477. for (i=0 ; i< (sizeof (*termio)) ; i++)
  3478. ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
  3479. *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
  3480. *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
  3481. *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
  3482. *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;
  3483. tty->termios.c_line = tmp_termio.c_line;
  3484. for(i=0 ; i < NCC ; i++)
  3485. tty->termios.c_cc[i] = tmp_termio.c_cc[i];
  3486. return 0;
  3487. }
  3488.  
  3489. int tty_ioctl(int dev, int cmd, int arg)
  3490. {
  3491. struct tty_struct * tty;
  3492. if (MAJOR(dev) == 5) {
  3493. dev=current->tty;
  3494. if (dev<0)
  3495. panic("tty_ioctl: dev<0");
  3496. } else
  3497. dev=MINOR(dev);
  3498. tty = dev + tty_table;
  3499. switch (cmd) {
  3500. case TCGETS:
  3501. return get_termios(tty,(struct termios *) arg);
  3502. case TCSETSF:
  3503. flush(&tty->read_q); /* fallthrough */
  3504. case TCSETSW:
  3505. wait_until_sent(tty); /* fallthrough */
  3506. case TCSETS:
  3507. return set_termios(tty,(struct termios *) arg);
  3508. case TCGETA:
  3509. return get_termio(tty,(struct termio *) arg);
  3510. case TCSETAF:
  3511. flush(&tty->read_q); /* fallthrough */
  3512. case TCSETAW:
  3513. wait_until_sent(tty); /* fallthrough */
  3514. case TCSETA:
  3515. return set_termio(tty,(struct termio *) arg);
  3516. case TCSBRK:
  3517. if (!arg) {
  3518. wait_until_sent(tty);
  3519. send_break(tty);
  3520. }
  3521. return 0;
  3522. case TCXONC:
  3523. return -EINVAL; /* not implemented */
  3524. case TCFLSH:
  3525. if (arg==0)
  3526. flush(&tty->read_q);
  3527. else if (arg==1)
  3528. flush(&tty->write_q);
  3529. else if (arg==2) {
  3530. flush(&tty->read_q);
  3531. flush(&tty->write_q);
  3532. } else
  3533. return -EINVAL;
  3534. return 0;
  3535. case TIOCEXCL:
  3536. return -EINVAL; /* not implemented */
  3537. case TIOCNXCL:
  3538. return -EINVAL; /* not implemented */
  3539. case TIOCSCTTY:
  3540. return -EINVAL; /* set controlling term NI */
  3541. case TIOCGPGRP:
  3542. verify_area((void *) arg,4);
  3543. put_fs_long(tty->pgrp,(unsigned long *) arg);
  3544. return 0;
  3545. case TIOCSPGRP:
  3546. tty->pgrp=get_fs_long((unsigned long *) arg);
  3547. return 0;
  3548. case TIOCOUTQ:
  3549. verify_area((void *) arg,4);
  3550. put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
  3551. return 0;
  3552. case TIOCSTI:
  3553. return -EINVAL; /* not implemented */
  3554. case TIOCGWINSZ:
  3555. return -EINVAL; /* not implemented */
  3556. case TIOCSWINSZ:
  3557. return -EINVAL; /* not implemented */
  3558. case TIOCMGET:
  3559. return -EINVAL; /* not implemented */
  3560. case TIOCMBIS:
  3561. return -EINVAL; /* not implemented */
  3562. case TIOCMBIC:
  3563. return -EINVAL; /* not implemented */
  3564. case TIOCMSET:
  3565. return -EINVAL; /* not implemented */
  3566. case TIOCGSOFTCAR:
  3567. return -EINVAL; /* not implemented */
  3568. case TIOCSSOFTCAR:
  3569. return -EINVAL; /* not implemented */
  3570. default:
  3571. return -EINVAL;
  3572. }
  3573. }
  3574.  
  3575. ------------------------------------------------------------------------
  3576.  
  3577. include/a.out.h
  3578.  
  3579. #ifndef _A_OUT_H
  3580. #define _A_OUT_H
  3581.  
  3582. #define __GNU_EXEC_MACROS__
  3583.  
  3584. struct exec {
  3585. unsigned long a_magic; /* Use macros N_MAGIC, etc for access */
  3586. unsigned a_text; /* length of text, in bytes */
  3587. unsigned a_data; /* length of data, in bytes */
  3588. unsigned a_bss; /* length of uninitialized data area for file, in bytes */
  3589. unsigned a_syms; /* length of symbol table data in file, in bytes */
  3590. unsigned a_entry; /* start address */
  3591. unsigned a_trsize; /* length of relocation info for text, in bytes */
  3592. unsigned a_drsize; /* length of relocation info for data, in bytes */
  3593. };
  3594.  
  3595. #ifndef N_MAGIC
  3596. #define N_MAGIC(exec) ((exec).a_magic)
  3597. #endif
  3598.  
  3599. #ifndef OMAGIC
  3600. /* Code indicating object file or impure executable. */
  3601. #define OMAGIC 0407
  3602. /* Code indicating pure executable. */
  3603. #define NMAGIC 0410
  3604. /* Code indicating demand-paged executable. */
  3605. #define ZMAGIC 0413
  3606. #endif /* not OMAGIC */
  3607.  
  3608. #ifndef N_BADMAG
  3609. #define N_BADMAG(x) \
  3610. (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
  3611. && N_MAGIC(x) != ZMAGIC)
  3612. #endif
  3613.  
  3614. #define _N_BADMAG(x) \
  3615. (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
  3616. && N_MAGIC(x) != ZMAGIC)
  3617.  
  3618. #define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec))
  3619.  
  3620. #ifndef N_TXTOFF
  3621. #define N_TXTOFF(x) \
  3622. (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
  3623. #endif
  3624.  
  3625. #ifndef N_DATOFF
  3626. #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
  3627. #endif
  3628.  
  3629. #ifndef N_TRELOFF
  3630. #define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
  3631. #endif
  3632.  
  3633. #ifndef N_DRELOFF
  3634. #define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
  3635. #endif
  3636.  
  3637. #ifndef N_SYMOFF
  3638. #define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
  3639. #endif
  3640.  
  3641. #ifndef N_STROFF
  3642. #define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
  3643. #endif
  3644.  
  3645. /* Address of text segment in memory after it is loaded. */
  3646. #ifndef N_TXTADDR
  3647. #define N_TXTADDR(x) 0
  3648. #endif
  3649.  
  3650. /* Address of data segment in memory after it is loaded.
  3651. Note that it is up to you to define SEGMENT_SIZE
  3652. on machines not listed here. */
  3653. #if defined(vax) || defined(hp300) || defined(pyr)
  3654. #define SEGMENT_SIZE PAGE_SIZE
  3655. #endif
  3656. #ifdef hp300
  3657. #define PAGE_SIZE 4096
  3658. #endif
  3659. #ifdef sony
  3660. #define SEGMENT_SIZE 0x2000
  3661. #endif /* Sony. */
  3662. #ifdef is68k
  3663. #define SEGMENT_SIZE 0x20000
  3664. #endif
  3665. #if defined(m68k) && defined(PORTAR)
  3666. #define PAGE_SIZE 0x400
  3667. #define SEGMENT_SIZE PAGE_SIZE
  3668. #endif
  3669.  
  3670. #define PAGE_SIZE 4096
  3671. #define SEGMENT_SIZE 1024
  3672.  
  3673. #define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
  3674.  
  3675. #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
  3676.  
  3677. #ifndef N_DATADDR
  3678. #define N_DATADDR(x) \
  3679. (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
  3680. : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
  3681. #endif
  3682.  
  3683. /* Address of bss segment in memory after it is loaded. */
  3684. #ifndef N_BSSADDR
  3685. #define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
  3686. #endif
  3687.  
  3688. #ifndef N_NLIST_DECLARED
  3689. struct nlist {
  3690. union {
  3691. char *n_name;
  3692. struct nlist *n_next;
  3693. long n_strx;
  3694. } n_un;
  3695. unsigned char n_type;
  3696. char n_other;
  3697. short n_desc;
  3698. unsigned long n_value;
  3699. };
  3700. #endif
  3701.  
  3702. #ifndef N_UNDF
  3703. #define N_UNDF 0
  3704. #endif
  3705. #ifndef N_ABS
  3706. #define N_ABS 2
  3707. #endif
  3708. #ifndef N_TEXT
  3709. #define N_TEXT 4
  3710. #endif
  3711. #ifndef N_DATA
  3712. #define N_DATA 6
  3713. #endif
  3714. #ifndef N_BSS
  3715. #define N_BSS 8
  3716. #endif
  3717. #ifndef N_COMM
  3718. #define N_COMM 18
  3719. #endif
  3720. #ifndef N_FN
  3721. #define N_FN 15
  3722. #endif
  3723.  
  3724. #ifndef N_EXT
  3725. #define N_EXT 1
  3726. #endif
  3727. #ifndef N_TYPE
  3728. #define N_TYPE 036
  3729. #endif
  3730. #ifndef N_STAB
  3731. #define N_STAB 0340
  3732. #endif
  3733.  
  3734. /* The following type indicates the definition of a symbol as being
  3735. an indirect reference to another symbol. The other symbol
  3736. appears as an undefined reference, immediately following this symbol.
  3737.  
  3738. Indirection is asymmetrical. The other symbol's value will be used
  3739. to satisfy requests for the indirect symbol, but not vice versa.
  3740. If the other symbol does not have a definition, libraries will
  3741. be searched to find a definition. */
  3742. #define N_INDR 0xa
  3743.  
  3744. /* The following symbols refer to set elements.
  3745. All the N_SET[ATDB] symbols with the same name form one set.
  3746. Space is allocated for the set in the text section, and each set
  3747. element's value is stored into one word of the space.
  3748. The first word of the space is the length of the set (number of elements).
  3749.  
  3750. The address of the set is made into an N_SETV symbol
  3751. whose name is the same as the name of the set.
  3752. This symbol acts like a N_DATA global symbol
  3753. in that it can satisfy undefined external references. */
  3754.  
  3755. /* These appear as input to LD, in a .o file. */
  3756. #define N_SETA 0x14 /* Absolute set element symbol */
  3757. #define N_SETT 0x16 /* Text set element symbol */
  3758. #define N_SETD 0x18 /* Data set element symbol */
  3759. #define N_SETB 0x1A /* Bss set element symbol */
  3760.  
  3761. /* This is output from LD. */
  3762. #define N_SETV 0x1C /* Pointer to set vector in data area. */
  3763.  
  3764. #ifndef N_RELOCATION_INFO_DECLARED
  3765.  
  3766. /* This structure describes a single relocation to be performed.
  3767. The text-relocation section of the file is a vector of these structures,
  3768. all of which apply to the text section.
  3769. Likewise, the data-relocation section applies to the data section. */
  3770.  
  3771. struct relocation_info
  3772. {
  3773. /* Address (within segment) to be relocated. */
  3774. int r_address;
  3775. /* The meaning of r_symbolnum depends on r_extern. */
  3776. unsigned int r_symbolnum:24;
  3777. /* Nonzero means value is a pc-relative offset
  3778. and it should be relocated for changes in its own address
  3779. as well as for changes in the symbol or section specified. */
  3780. unsigned int r_pcrel:1;
  3781. /* Length (as exponent of 2) of the field to be relocated.
  3782. Thus, a value of 2 indicates 1<<2 bytes. */
  3783. unsigned int r_length:2;
  3784. /* 1 => relocate with value of symbol.
  3785. r_symbolnum is the index of the symbol
  3786. in file's the symbol table.
  3787. 0 => relocate with the address of a segment.
  3788. r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
  3789. (the N_EXT bit may be set also, but signifies nothing). */
  3790. unsigned int r_extern:1;
  3791. /* Four bits that aren't used, but when writing an object file
  3792. it is desirable to clear them. */
  3793. unsigned int r_pad:4;
  3794. };
  3795. #endif /* no N_RELOCATION_INFO_DECLARED. */
  3796.  
  3797.  
  3798. #endif /* __A_OUT_GNU_H__ */
  3799.  
  3800. ------------------------------------------------------------------------
  3801.  
  3802. include/asm/io.h
  3803.  
  3804. #define outb(value,port) \
  3805. __asm__ ("outb %%al,%%dx"::"a" (value),"d" (port))
  3806.  
  3807.  
  3808. #define inb(port) ({ \
  3809. unsigned char _v; \
  3810. __asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \
  3811. _v; \
  3812. })
  3813.  
  3814. #define outb_p(value,port) \
  3815. __asm__ ("outb %%al,%%dx\n" \
  3816. "\tjmp 1f\n" \
  3817. "1:\tjmp 1f\n" \
  3818. "1:"::"a" (value),"d" (port))
  3819.  
  3820. #define inb_p(port) ({ \
  3821. unsigned char _v; \
  3822. __asm__ volatile ("inb %%dx,%%al\n" \
  3823. "\tjmp 1f\n" \
  3824. "1:\tjmp 1f\n" \
  3825. "1:":"=a" (_v):"d" (port)); \
  3826. _v; \
  3827. })
  3828.  
  3829. ------------------------------------------------------------------------
  3830.  
  3831. include/asm/memory.h
  3832.  
  3833. /*
  3834. * NOTE!!! memcpy(dest,src,n) assumes ds=es=normal data segment. This
  3835. * goes for all kernel functions (ds=es=kernel space, fs=local data,
  3836. * gs=null), as well as for all well-behaving user programs (ds=es=
  3837. * user data space). This is NOT a bug, as any user program that changes
  3838. * es deserves to die if it isn't careful.
  3839. */
  3840. #define memcpy(dest,src,n) ({ \
  3841. void * _res = dest; \
  3842. __asm__ ("cld;rep;movsb" \
  3843. ::"D" ((long)(_res)),"S" ((long)(src)),"c" ((long) (n)) \
  3844. :"di","si","cx"); \
  3845. _res; \
  3846. })
  3847.  
  3848. ------------------------------------------------------------------------
  3849.  
  3850. include/asm/segment.h
  3851.  
  3852. extern inline unsigned char get_fs_byte(const char * addr)
  3853. {
  3854. unsigned register char _v;
  3855.  
  3856. __asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
  3857. return _v;
  3858. }
  3859.  
  3860. extern inline unsigned short get_fs_word(const unsigned short *addr)
  3861. {
  3862. unsigned short _v;
  3863.  
  3864. __asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr));
  3865. return _v;
  3866. }
  3867.  
  3868. extern inline unsigned long get_fs_long(const unsigned long *addr)
  3869. {
  3870. unsigned long _v;
  3871.  
  3872. __asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
  3873. return _v;
  3874. }
  3875.  
  3876. extern inline void put_fs_byte(char val,char *addr)
  3877. {
  3878. __asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr));
  3879. }
  3880.  
  3881. extern inline void put_fs_word(short val,short * addr)
  3882. {
  3883. __asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr));
  3884. }
  3885.  
  3886. extern inline void put_fs_long(unsigned long val,unsigned long * addr)
  3887. {
  3888. __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
  3889. }
  3890.  
  3891. ------------------------------------------------------------------------
  3892.  
  3893. include/asm/system.h
  3894.  
  3895. #define move_to_user_mode() \
  3896. __asm__ ("movl %%esp,%%eax\n\t" \
  3897. "pushl $0x17\n\t" \
  3898. "pushl %%eax\n\t" \
  3899. "pushfl\n\t" \
  3900. "pushl $0x0f\n\t" \
  3901. "pushl $1f\n\t" \
  3902. "iret\n" \
  3903. "1:\tmovl $0x17,%%eax\n\t" \
  3904. "movw %%ax,%%ds\n\t" \
  3905. "movw %%ax,%%es\n\t" \
  3906. "movw %%ax,%%fs\n\t" \
  3907. "movw %%ax,%%gs" \
  3908. :::"ax")
  3909.  
  3910. #define sti() __asm__ ("sti"::)
  3911. #define cli() __asm__ ("cli"::)
  3912. #define nop() __asm__ ("nop"::)
  3913.  
  3914. #define iret() __asm__ ("iret"::)
  3915.  
  3916. #define _set_gate(gate_addr,type,dpl,addr) \
  3917. __asm__ ("movw %%dx,%%ax\n\t" \
  3918. "movw %0,%%dx\n\t" \
  3919. "movl %%eax,%1\n\t" \
  3920. "movl %%edx,%2" \
  3921. : \
  3922. : "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
  3923. "o" (*((char *) (gate_addr))), \
  3924. "o" (*(4+(char *) (gate_addr))), \
  3925. "d" ((char *) (addr)),"a" (0x00080000))
  3926.  
  3927. #define set_intr_gate(n,addr) \
  3928. _set_gate(&idt[n],14,0,addr)
  3929.  
  3930. #define set_trap_gate(n,addr) \
  3931. _set_gate(&idt[n],15,0,addr)
  3932.  
  3933. #define set_system_gate(n,addr) \
  3934. _set_gate(&idt[n],15,3,addr)
  3935.  
  3936. #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
  3937. *(gate_addr) = ((base) & 0xff000000) | \
  3938. (((base) & 0x00ff0000)>>16) | \
  3939. ((limit) & 0xf0000) | \
  3940. ((dpl)<<13) | \
  3941. (0x00408000) | \
  3942. ((type)<<8); \
  3943. *((gate_addr)+1) = (((base) & 0x0000ffff)<<16) | \
  3944. ((limit) & 0x0ffff); }
  3945.  
  3946. #define _set_tssldt_desc(n,addr,type) \
  3947. __asm__ ("movw $104,%1\n\t" \
  3948. "movw %%ax,%2\n\t" \
  3949. "rorl $16,%%eax\n\t" \
  3950. "movb %%al,%3\n\t" \
  3951. "movb $" type ",%4\n\t" \
  3952. "movb $0x00,%5\n\t" \
  3953. "movb %%ah,%6\n\t" \
  3954. "rorl $16,%%eax" \
  3955. ::"a" (addr), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
  3956. "m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
  3957. )
  3958.  
  3959. #define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x89")
  3960. #define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x82")
  3961.  
  3962. ------------------------------------------------------------------------
  3963.  
  3964. include/const.h
  3965.  
  3966. #ifndef _CONST_H
  3967. #define _CONST_H
  3968.  
  3969. #define BUFFER_END 0x200000
  3970.  
  3971. #define I_TYPE 0170000
  3972. #define I_DIRECTORY 0040000
  3973. #define I_REGULAR 0100000
  3974. #define I_BLOCK_SPECIAL 0060000
  3975. #define I_CHAR_SPECIAL 0020000
  3976. #define I_NAMED_PIPE 0010000
  3977. #define I_SET_UID_BIT 0004000
  3978. #define I_SET_GID_BIT 0002000
  3979.  
  3980. #endif
  3981.  
  3982. ------------------------------------------------------------------------
  3983.  
  3984. include/ctype.h
  3985.  
  3986. #ifndef _CTYPE_H
  3987. #define _CTYPE_H
  3988.  
  3989. #define _U 0x01 /* upper */
  3990. #define _L 0x02 /* lower */
  3991. #define _D 0x04 /* digit */
  3992. #define _C 0x08 /* cntrl */
  3993. #define _P 0x10 /* punct */
  3994. #define _S 0x20 /* white space (space/lf/tab) */
  3995. #define _X 0x40 /* hex digit */
  3996. #define _SP 0x80 /* hard space (0x20) */
  3997.  
  3998. extern unsigned char _ctype[];
  3999. extern char _ctmp;
  4000.  
  4001. #define isalnum(c) ((_ctype+1)[c]&(_U|_L|_D))
  4002. #define isalpha(c) ((_ctype+1)[c]&(_U|_L))
  4003. #define iscntrl(c) ((_ctype+1)[c]&(_C))
  4004. #define isdigit(c) ((_ctype+1)[c]&(_D))
  4005. #define isgraph(c) ((_ctype+1)[c]&(_P|_U|_L|_D))
  4006. #define islower(c) ((_ctype+1)[c]&(_L))
  4007. #define isprint(c) ((_ctype+1)[c]&(_P|_U|_L|_D|_SP))
  4008. #define ispunct(c) ((_ctype+1)[c]&(_P))
  4009. #define isspace(c) ((_ctype+1)[c]&(_S))
  4010. #define isupper(c) ((_ctype+1)[c]&(_U))
  4011. #define isxdigit(c) ((_ctype+1)[c]&(_D|_X))
  4012.  
  4013. #define isascii(c) (((unsigned) c)<=0x7f)
  4014. #define toascii(c) (((unsigned) c)&0x7f)
  4015.  
  4016. #define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp+('a'+'A'):_ctmp)
  4017. #define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp+('A'-'a'):_ctmp)
  4018.  
  4019. #endif
  4020.  
  4021. ------------------------------------------------------------------------
  4022.  
  4023. include/errno.h
  4024.  
  4025. #ifndef _ERRNO_H
  4026. #define _ERRNO_H
  4027.  
  4028. /*
  4029. * ok, as I hadn't got any other source of information about
  4030. * possible error numbers, I was forced to use the same numbers
  4031. * as minix.
  4032. * Hopefully these are posix or something. I wouldn't know (and posix
  4033. * isn't telling me - they want $$$ for their f***ing standard).
  4034. *
  4035. * We don't use the _SIGN cludge of minix, so kernel returns must
  4036. * see to the sign by themselves.
  4037. *
  4038. * NOTE! Remember to change strerror() if you change this file!
  4039. */
  4040.  
  4041. extern int errno;
  4042.  
  4043. #define ERROR 99
  4044. #define EPERM 1
  4045. #define ENOENT 2
  4046. #define ESRCH 3
  4047. #define EINTR 4
  4048. #define EIO 5
  4049. #define ENXIO 6
  4050. #define E2BIG 7
  4051. #define ENOEXEC 8
  4052. #define EBADF 9
  4053. #define ECHILD 10
  4054. #define EAGAIN 11
  4055. #define ENOMEM 12
  4056. #define EACCES 13
  4057. #define EFAULT 14
  4058. #define ENOTBLK 15
  4059. #define EBUSY 16
  4060. #define EEXIST 17
  4061. #define EXDEV 18
  4062. #define ENODEV 19
  4063. #define ENOTDIR 20
  4064. #define EISDIR 21
  4065. #define EINVAL 22
  4066. #define ENFILE 23
  4067. #define EMFILE 24
  4068. #define ENOTTY 25
  4069. #define ETXTBSY 26
  4070. #define EFBIG 27
  4071. #define ENOSPC 28
  4072. #define ESPIPE 29
  4073. #define EROFS 30
  4074. #define EMLINK 31
  4075. #define EPIPE 32
  4076. #define EDOM 33
  4077. #define ERANGE 34
  4078. #define EDEADLK 35
  4079. #define ENAMETOOLONG 36
  4080. #define ENOLCK 37
  4081. #define ENOSYS 38
  4082. #define ENOTEMPTY 39
  4083.  
  4084. #endif
  4085.  
  4086. ------------------------------------------------------------------------
  4087.  
  4088. include/fcntl.h
  4089.  
  4090. #ifndef _FCNTL_H
  4091. #define _FCNTL_H
  4092.  
  4093. #include <sys/types.h>
  4094.  
  4095. /* open/fcntl - NOCTTY, NDELAY isn't implemented yet */
  4096. #define O_ACCMODE 00003
  4097. #define O_RDONLY 00
  4098. #define O_WRONLY 01
  4099. #define O_RDWR 02
  4100. #define O_CREAT 00100 /* not fcntl */
  4101. #define O_EXCL 00200 /* not fcntl */
  4102. #define O_NOCTTY 00400 /* not fcntl */
  4103. #define O_TRUNC 01000 /* not fcntl */
  4104. #define O_APPEND 02000
  4105. #define O_NONBLOCK 04000 /* not fcntl */
  4106. #define O_NDELAY O_NONBLOCK
  4107.  
  4108. /* Defines for fcntl-commands. Note that currently
  4109. * locking isn't supported, and other things aren't really
  4110. * tested.
  4111. */
  4112. #define F_DUPFD 0 /* dup */
  4113. #define F_GETFD 1 /* get f_flags */
  4114. #define F_SETFD 2 /* set f_flags */
  4115. #define F_GETFL 3 /* more flags (cloexec) */
  4116. #define F_SETFL 4
  4117. #define F_GETLK 5 /* not implemented */
  4118. #define F_SETLK 6
  4119. #define F_SETLKW 7
  4120.  
  4121. /* for F_[GET|SET]FL */
  4122. #define FD_CLOEXEC 1 /* actually anything with low bit set goes */
  4123.  
  4124. /* Ok, these are locking features, and aren't implemented at any
  4125. * level. POSIX wants them.
  4126. */
  4127. #define F_RDLCK 0
  4128. #define F_WRLCK 1
  4129. #define F_UNLCK 2
  4130.  
  4131. /* Once again - not implemented, but ... */
  4132. struct flock {
  4133. short l_type;
  4134. short l_whence;
  4135. off_t l_start;
  4136. off_t l_len;
  4137. pid_t l_pid;
  4138. };
  4139.  
  4140. extern int creat(const char * filename,mode_t mode);
  4141. extern int fcntl(int fildes,int cmd, ...);
  4142. extern int open(const char * filename, int flags, ...);
  4143.  
  4144. #endif
  4145.  
  4146. ------------------------------------------------------------------------
  4147.  
  4148. include/linux/config.h
  4149.  
  4150. #ifndef _CONFIG_H
  4151. #define _CONFIG_H
  4152.  
  4153. /* #define LASU_HD */
  4154. #define LINUS_HD
  4155.  
  4156. /*
  4157. * Amount of ram memory (in bytes, 640k-1M not discounted). Currently 8Mb.
  4158. * Don't make this bigger without making sure that there are enough page
  4159. * directory entries (boot/head.s)
  4160. */
  4161. #if defined(LINUS_HD)
  4162. #define HIGH_MEMORY (0x800000)
  4163. #elif defined(LASU_HD)
  4164. #define HIGH_MEMORY (0x400000)
  4165. #else
  4166. #error "must define hd"
  4167. #endif
  4168.  
  4169. /* End of buffer memory. Must be 0xA0000, or > 0x100000, 4096-byte aligned */
  4170. #if (HIGH_MEMORY>=0x600000)
  4171. #define BUFFER_END 0x200000
  4172. #else
  4173. #define BUFFER_END 0xA0000
  4174. #endif
  4175.  
  4176. /* Root device at bootup. */
  4177. #if defined(LINUS_HD)
  4178. #define ROOT_DEV 0x306
  4179. #elif defined(LASU_HD)
  4180. #define ROOT_DEV 0x302
  4181. #else
  4182. #error "must define HD"
  4183. #endif
  4184.  
  4185. /*
  4186. * HD type. If 2, put 2 structures with a comma. If just 1, put
  4187. * only 1 struct. The structs are { HEAD, SECTOR, TRACKS, WPCOM, LZONE, CTL }
  4188. *
  4189. * NOTE. CTL is supposed to be 0 for drives with less than 8 heads, and
  4190. * 8 if heads >= 8. Don't know why, and I haven't tested it on a drive with
  4191. * more than 8 heads, but that is what the bios-listings seem to imply. I
  4192. * just love not having a manual.
  4193. */
  4194. #if defined(LASU_HD)
  4195. #define HD_TYPE { 7,35,915,65536,920,0 }
  4196. #elif defined(LINUS_HD)
  4197. #define HD_TYPE { 5,17,980,300,980,0 },{ 5,17,980,300,980,0 }
  4198. #else
  4199. #error "must define a hard-disk type"
  4200. #endif
  4201.  
  4202. #endif
  4203.  
  4204. ------------------------------------------------------------------------
  4205.  
  4206. include/linux/fs.h
  4207.  
  4208. /*
  4209. * This file has definitions for some important file table
  4210. * structures etc.
  4211. */
  4212.  
  4213. #ifndef _FS_H
  4214. #define _FS_H
  4215.  
  4216. #include <sys/types.h>
  4217.  
  4218. /* devices are as follows: (same as minix, so we can use the minix
  4219. * file system. These are major numbers.)
  4220. *
  4221. * 0 - unused (nodev)
  4222. * 1 - /dev/mem
  4223. * 2 - /dev/fd
  4224. * 3 - /dev/hd
  4225. * 4 - /dev/ttyx
  4226. * 5 - /dev/tty
  4227. * 6 - /dev/lp
  4228. * 7 - unnamed pipes
  4229. */
  4230.  
  4231. #define IS_BLOCKDEV(x) ((x)==2 || (x)==3)
  4232.  
  4233. #define READ 0
  4234. #define WRITE 1
  4235.  
  4236. void buffer_init(void);
  4237.  
  4238. #define MAJOR(a) (((unsigned)(a))>>8)
  4239. #define MINOR(a) ((a)&0xff)
  4240.  
  4241. #define NAME_LEN 14
  4242.  
  4243. #define I_MAP_SLOTS 8
  4244. #define Z_MAP_SLOTS 8
  4245. #define SUPER_MAGIC 0x137F
  4246.  
  4247. #define NR_OPEN 20
  4248. #define NR_INODE 32
  4249. #define NR_FILE 64
  4250. #define NR_SUPER 8
  4251. #define NR_HASH 307
  4252. #define NR_BUFFERS nr_buffers
  4253. #define BLOCK_SIZE 1024
  4254. #ifndef NULL
  4255. #define NULL ((void *) 0)
  4256. #endif
  4257.  
  4258. #define INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct d_inode)))
  4259. #define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry)))
  4260.  
  4261. typedef char buffer_block[BLOCK_SIZE];
  4262.  
  4263. struct buffer_head {
  4264. char * b_data; /* pointer to data block (1024 bytes) */
  4265. unsigned short b_dev; /* device (0 = free) */
  4266. unsigned short b_blocknr; /* block number */
  4267. unsigned char b_uptodate;
  4268. unsigned char b_dirt; /* 0-clean,1-dirty */
  4269. unsigned char b_count; /* users using this block */
  4270. unsigned char b_lock; /* 0 - ok, 1 -locked */
  4271. struct task_struct * b_wait;
  4272. struct buffer_head * b_prev;
  4273. struct buffer_head * b_next;
  4274. struct buffer_head * b_prev_free;
  4275. struct buffer_head * b_next_free;
  4276. };
  4277.  
  4278. struct d_inode {
  4279. unsigned short i_mode;
  4280. unsigned short i_uid;
  4281. unsigned long i_size;
  4282. unsigned long i_time;
  4283. unsigned char i_gid;
  4284. unsigned char i_nlinks;
  4285. unsigned short i_zone[9];
  4286. };
  4287.  
  4288. struct m_inode {
  4289. unsigned short i_mode;
  4290. unsigned short i_uid;
  4291. unsigned long i_size;
  4292. unsigned long i_mtime;
  4293. unsigned char i_gid;
  4294. unsigned char i_nlinks;
  4295. unsigned short i_zone[9];
  4296. /* these are in memory also */
  4297. struct task_struct * i_wait;
  4298. unsigned long i_atime;
  4299. unsigned long i_ctime;
  4300. unsigned short i_dev;
  4301. unsigned short i_num;
  4302. unsigned short i_count;
  4303. unsigned char i_lock;
  4304. unsigned char i_dirt;
  4305. unsigned char i_pipe;
  4306. unsigned char i_mount;
  4307. unsigned char i_seek;
  4308. unsigned char i_update;
  4309. };
  4310.  
  4311. #define PIPE_HEAD(inode) (((long *)((inode).i_zone))[0])
  4312. #define PIPE_TAIL(inode) (((long *)((inode).i_zone))[1])
  4313. #define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))
  4314. #define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode))
  4315. #define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
  4316. #define INC_PIPE(head) \
  4317. __asm__("incl %0\n\tandl $4095,%0"::"m" (head))
  4318.  
  4319. struct file {
  4320. unsigned short f_mode;
  4321. unsigned short f_flags;
  4322. unsigned short f_count;
  4323. struct m_inode * f_inode;
  4324. off_t f_pos;
  4325. };
  4326.  
  4327. struct super_block {
  4328. unsigned short s_ninodes;
  4329. unsigned short s_nzones;
  4330. unsigned short s_imap_blocks;
  4331. unsigned short s_zmap_blocks;
  4332. unsigned short s_firstdatazone;
  4333. unsigned short s_log_zone_size;
  4334. unsigned long s_max_size;
  4335. unsigned short s_magic;
  4336. /* These are only in memory */
  4337. struct buffer_head * s_imap[8];
  4338. struct buffer_head * s_zmap[8];
  4339. unsigned short s_dev;
  4340. struct m_inode * s_isup;
  4341. struct m_inode * s_imount;
  4342. unsigned long s_time;
  4343. unsigned char s_rd_only;
  4344. unsigned char s_dirt;
  4345. };
  4346.  
  4347. struct dir_entry {
  4348. unsigned short inode;
  4349. char name[NAME_LEN];
  4350. };
  4351.  
  4352. extern struct m_inode inode_table[NR_INODE];
  4353. extern struct file file_table[NR_FILE];
  4354. extern struct super_block super_block[NR_SUPER];
  4355. extern struct buffer_head * start_buffer;
  4356. extern int nr_buffers;
  4357.  
  4358. extern void truncate(struct m_inode * inode);
  4359. extern void sync_inodes(void);
  4360. extern void wait_on(struct m_inode * inode);
  4361. extern int bmap(struct m_inode * inode,int block);
  4362. extern int create_block(struct m_inode * inode,int block);
  4363. extern struct m_inode * namei(const char * pathname);
  4364. extern int open_namei(const char * pathname, int flag, int mode,
  4365. struct m_inode ** res_inode);
  4366. extern void iput(struct m_inode * inode);
  4367. extern struct m_inode * iget(int dev,int nr);
  4368. extern struct m_inode * get_empty_inode(void);
  4369. extern struct m_inode * get_pipe_inode(void);
  4370. extern struct buffer_head * get_hash_table(int dev, int block);
  4371. extern struct buffer_head * getblk(int dev, int block);
  4372. extern void ll_rw_block(int rw, struct buffer_head * bh);
  4373. extern void brelse(struct buffer_head * buf);
  4374. extern struct buffer_head * bread(int dev,int block);
  4375. extern int new_block(int dev);
  4376. extern void free_block(int dev, int block);
  4377. extern struct m_inode * new_inode(int dev);
  4378. extern void free_inode(struct m_inode * inode);
  4379.  
  4380. extern void mount_root(void);
  4381.  
  4382. extern inline struct super_block * get_super(int dev)
  4383. {
  4384. struct super_block * s;
  4385.  
  4386. for(s = 0+super_block;s < NR_SUPER+super_block; s++)
  4387. if (s->s_dev == dev)
  4388. return s;
  4389. return NULL;
  4390. }
  4391.  
  4392. #endif
  4393.  
  4394. ------------------------------------------------------------------------
  4395.  
  4396. include/linux/hdreg.h
  4397.  
  4398. /*
  4399. * This file contains some defines for the AT-hd-controller.
  4400. * Various sources. Check out some definitions (see comments with
  4401. * a ques).
  4402. */
  4403. #ifndef _HDREG_H
  4404. #define _HDREG_H
  4405.  
  4406. /* currently supports only 1 hd, put type here */
  4407. #define HARD_DISK_TYPE 17
  4408.  
  4409. /*
  4410. * Ok, hard-disk-type is currently hardcoded. Not beatiful,
  4411. * but easier. We don't use BIOS for anything else, why should
  4412. * we get HD-type from it? Get these values from Reference Guide.
  4413. */
  4414.  
  4415. #if HARD_DISK_TYPE == 17
  4416. #define _CYL 977
  4417. #define _HEAD 5
  4418. #define __WPCOM 300
  4419. #define _LZONE 977
  4420. #define _SECT 17
  4421. #define _CTL 0
  4422. #elif HARD_DISK_TYPE == 18
  4423. #define _CYL 977
  4424. #define _HEAD 7
  4425. #define __WPCOM (-1)
  4426. #define _LZONE 977
  4427. #define _SECT 17
  4428. #define _CTL 0
  4429. #else
  4430. #error Define HARD_DISK_TYPE and parameters, add your own entries as well
  4431. #endif
  4432.  
  4433. /* Controller wants just wp-com/4 */
  4434. #if __WPCOM >= 0
  4435. #define _WPCOM ((__WPCOM)>>2)
  4436. #else
  4437. #define _WPCOM __WPCOM
  4438. #endif
  4439.  
  4440. /* Hd controller regs. Ref: IBM AT Bios-listing */
  4441. #define HD_DATA 0x1f0 /* _CTL when writing */
  4442. #define HD_ERROR 0x1f1 /* see err-bits */
  4443. #define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
  4444. #define HD_SECTOR 0x1f3 /* starting sector */
  4445. #define HD_LCYL 0x1f4 /* starting cylinder */
  4446. #define HD_HCYL 0x1f5 /* high byte of starting cyl */
  4447. #define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
  4448. #define HD_STATUS 0x1f7 /* see status-bits */
  4449. #define HD_PRECOMP HD_ERROR /* same io address, read=error, write=precomp */
  4450. #define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
  4451.  
  4452. #define HD_CMD 0x3f6
  4453.  
  4454. /* Bits of HD_STATUS */
  4455. #define ERR_STAT 0x01
  4456. #define INDEX_STAT 0x02
  4457. #define ECC_STAT 0x04 /* Corrected error */
  4458. #define DRQ_STAT 0x08
  4459. #define SEEK_STAT 0x10
  4460. #define WRERR_STAT 0x20
  4461. #define READY_STAT 0x40
  4462. #define BUSY_STAT 0x80
  4463.  
  4464. /* Values for HD_COMMAND */
  4465. #define WIN_RESTORE 0x10
  4466. #define WIN_READ 0x20
  4467. #define WIN_WRITE 0x30
  4468. #define WIN_VERIFY 0x40
  4469. #define WIN_FORMAT 0x50
  4470. #define WIN_INIT 0x60
  4471. #define WIN_SEEK 0x70
  4472. #define WIN_DIAGNOSE 0x90
  4473. #define WIN_SPECIFY 0x91
  4474.  
  4475. /* Bits for HD_ERROR */
  4476. #define MARK_ERR 0x01 /* Bad address mark ? */
  4477. #define TRK0_ERR 0x02 /* couldn't find track 0 */
  4478. #define ABRT_ERR 0x04 /* ? */
  4479. #define ID_ERR 0x10 /* ? */
  4480. #define ECC_ERR 0x40 /* ? */
  4481. #define BBD_ERR 0x80 /* ? */
  4482.  
  4483. struct partition {
  4484. unsigned char boot_ind; /* 0x80 - active (unused) */
  4485. unsigned char head; /* ? */
  4486. unsigned char sector; /* ? */
  4487. unsigned char cyl; /* ? */
  4488. unsigned char sys_ind; /* ? */
  4489. unsigned char end_head; /* ? */
  4490. unsigned char end_sector; /* ? */
  4491. unsigned char end_cyl; /* ? */
  4492. unsigned int start_sect; /* starting sector counting from 0 */
  4493. unsigned int nr_sects; /* nr of sectors in partition */
  4494. };
  4495.  
  4496. #endif
  4497.  
  4498. ------------------------------------------------------------------------
  4499.  
  4500. include/linux/head.h
  4501.  
  4502. #ifndef _HEAD_H
  4503. #define _HEAD_H
  4504.  
  4505. typedef struct desc_struct {
  4506. unsigned long a,b;
  4507. } desc_table[256];
  4508.  
  4509. extern unsigned long pg_dir[1024];
  4510. extern desc_table idt,gdt;
  4511.  
  4512. #define GDT_NUL 0
  4513. #define GDT_CODE 1
  4514. #define GDT_DATA 2
  4515. #define GDT_TMP 3
  4516.  
  4517. #define LDT_NUL 0
  4518. #define LDT_CODE 1
  4519. #define LDT_DATA 2
  4520.  
  4521. #endif
  4522.  
  4523. ------------------------------------------------------------------------
  4524.  
  4525. include/linux/kernel.h
  4526.  
  4527. /*
  4528. * 'kernel.h' contains some often-used function prototypes etc
  4529. */
  4530. void verify_area(void * addr,int count);
  4531. volatile void panic(const char * str);
  4532. int printf(const char * fmt, ...);
  4533. int printk(const char * fmt, ...);
  4534. int tty_write(unsigned ch,char * buf,int count);
  4535.  
  4536. ------------------------------------------------------------------------
  4537.  
  4538. include/linux/mm.h
  4539.  
  4540. #ifndef _MM_H
  4541. #define _MM_H
  4542.  
  4543. #define PAGE_SIZE 4096
  4544.  
  4545. extern unsigned long get_free_page(void);
  4546. extern unsigned long put_page(unsigned long page,unsigned long address);
  4547. extern void free_page(unsigned long addr);
  4548.  
  4549. #endif
  4550.  
  4551. ------------------------------------------------------------------------
  4552.  
  4553. include/linux/sched.h
  4554.  
  4555. #ifndef _SCHED_H
  4556. #define _SCHED_H
  4557.  
  4558. #define NR_TASKS 64
  4559. #define HZ 100
  4560.  
  4561. #define FIRST_TASK task[0]
  4562. #define LAST_TASK task[NR_TASKS-1]
  4563.  
  4564. #include <linux/head.h>
  4565. #include <linux/fs.h>
  4566. #include <linux/mm.h>
  4567.  
  4568. #if (NR_OPEN > 32)
  4569. #error "Currently the close-on-exec-flags are in one word, max 32 files/proc"
  4570. #endif
  4571.  
  4572. #define TASK_RUNNING 0
  4573. #define TASK_INTERRUPTIBLE 1
  4574. #define TASK_UNINTERRUPTIBLE 2
  4575. #define TASK_ZOMBIE 3
  4576. #define TASK_STOPPED 4
  4577.  
  4578. #ifndef NULL
  4579. #define NULL ((void *) 0)
  4580. #endif
  4581.  
  4582. extern int copy_page_tables(unsigned long from, unsigned long to, long size);
  4583. extern int free_page_tables(unsigned long from, long size);
  4584.  
  4585. extern void sched_init(void);
  4586. extern void schedule(void);
  4587. extern void trap_init(void);
  4588. extern void panic(const char * str);
  4589. extern int tty_write(unsigned minor,char * buf,int count);
  4590.  
  4591. typedef int (*fn_ptr)();
  4592.  
  4593. struct i387_struct {
  4594. long cwd;
  4595. long swd;
  4596. long twd;
  4597. long fip;
  4598. long fcs;
  4599. long foo;
  4600. long fos;
  4601. long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
  4602. };
  4603.  
  4604. struct tss_struct {
  4605. long back_link; /* 16 high bits zero */
  4606. long esp0;
  4607. long ss0; /* 16 high bits zero */
  4608. long esp1;
  4609. long ss1; /* 16 high bits zero */
  4610. long esp2;
  4611. long ss2; /* 16 high bits zero */
  4612. long cr3;
  4613. long eip;
  4614. long eflags;
  4615. long eax,ecx,edx,ebx;
  4616. long esp;
  4617. long ebp;
  4618. long esi;
  4619. long edi;
  4620. long es; /* 16 high bits zero */
  4621. long cs; /* 16 high bits zero */
  4622. long ss; /* 16 high bits zero */
  4623. long ds; /* 16 high bits zero */
  4624. long fs; /* 16 high bits zero */
  4625. long gs; /* 16 high bits zero */
  4626. long ldt; /* 16 high bits zero */
  4627. long trace_bitmap; /* bits: trace 0, bitmap 16-31 */
  4628. struct i387_struct i387;
  4629. };
  4630.  
  4631. struct task_struct {
  4632. /* these are hardcoded - don't touch */
  4633. long state; /* -1 unrunnable, 0 runnable, >0 stopped */
  4634. long counter;
  4635. long priority;
  4636. long signal;
  4637. fn_ptr sig_restorer;
  4638. fn_ptr sig_fn[32];
  4639. /* various fields */
  4640. int exit_code;
  4641. unsigned long end_code,end_data,brk,start_stack;
  4642. long pid,father,pgrp,session,leader;
  4643. unsigned short uid,euid,suid;
  4644. unsigned short gid,egid,sgid;
  4645. long alarm;
  4646. long utime,stime,cutime,cstime,start_time;
  4647. unsigned short used_math;
  4648. /* file system info */
  4649. int tty; /* -1 if no tty, so it must be signed */
  4650. unsigned short umask;
  4651. struct m_inode * pwd;
  4652. struct m_inode * root;
  4653. unsigned long close_on_exec;
  4654. struct file * filp[NR_OPEN];
  4655. /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
  4656. struct desc_struct ldt[3];
  4657. /* tss for this task */
  4658. struct tss_struct tss;
  4659. };
  4660.  
  4661. /*
  4662. * INIT_TASK is used to set up the first task table, touch at
  4663. * your own risk!. Base=0, limit=0x9ffff (=640kB)
  4664. */
  4665. #define INIT_TASK \
  4666. /* state etc */ { 0,15,15, \
  4667. /* signals */ 0,NULL,{(fn_ptr) 0,}, \
  4668. /* ec,brk... */ 0,0,0,0,0, \
  4669. /* pid etc.. */ 0,-1,0,0,0, \
  4670. /* uid etc */ 0,0,0,0,0,0, \
  4671. /* alarm */ 0,0,0,0,0,0, \
  4672. /* math */ 0, \
  4673. /* fs info */ -1,0133,NULL,NULL,0, \
  4674. /* filp */ {NULL,}, \
  4675. { \
  4676. {0,0}, \
  4677. /* ldt */ {0x9f,0xc0fa00}, \
  4678. {0x9f,0xc0f200}, \
  4679. }, \
  4680. /*tss*/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\
  4681. 0,0,0,0,0,0,0,0, \
  4682. 0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
  4683. _LDT(0),0x80000000, \
  4684. {} \
  4685. }, \
  4686. }
  4687.  
  4688. extern struct task_struct *task[NR_TASKS];
  4689. extern struct task_struct *last_task_used_math;
  4690. extern struct task_struct *current;
  4691. extern long volatile jiffies;
  4692. extern long startup_time;
  4693.  
  4694. #define CURRENT_TIME (startup_time+jiffies/HZ)
  4695.  
  4696. extern void sleep_on(struct task_struct ** p);
  4697. extern void interruptible_sleep_on(struct task_struct ** p);
  4698. extern void wake_up(struct task_struct ** p);
  4699.  
  4700. /*
  4701. * Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall
  4702. * 4-TSS0, 5-LDT0, 6-TSS1 etc ...
  4703. */
  4704. #define FIRST_TSS_ENTRY 4
  4705. #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
  4706. #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
  4707. #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
  4708. #define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n)))
  4709. #define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n)))
  4710. #define str(n) \
  4711. __asm__("str %%ax\n\t" \
  4712. "subl %2,%%eax\n\t" \
  4713. "shrl $4,%%eax" \
  4714. :"=a" (n) \
  4715. :"a" (0),"i" (FIRST_TSS_ENTRY<<3))
  4716. /*
  4717. * switch_to(n) should switch tasks to task nr n, first
  4718. * checking that n isn't the current task, in which case it does nothing.
  4719. * This also clears the TS-flag if the task we switched to has used
  4720. * tha math co-processor latest.
  4721. */
  4722. #define switch_to(n) {\
  4723. struct {long a,b;} __tmp; \
  4724. __asm__("cmpl %%ecx,_current\n\t" \
  4725. "je 1f\n\t" \
  4726. "xchgl %%ecx,_current\n\t" \
  4727. "movw %%dx,%1\n\t" \
  4728. "ljmp %0\n\t" \
  4729. "cmpl %%ecx,%2\n\t" \
  4730. "jne 1f\n\t" \
  4731. "clts\n" \
  4732. "1:" \
  4733. ::"m" (*&__tmp.a),"m" (*&__tmp.b), \
  4734. "m" (last_task_used_math),"d" _TSS(n),"c" ((long) task[n])); \
  4735. }
  4736.  
  4737. #define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000)
  4738.  
  4739. #define _set_base(addr,base) \
  4740. __asm__("movw %%dx,%0\n\t" \
  4741. "rorl $16,%%edx\n\t" \
  4742. "movb %%dl,%1\n\t" \
  4743. "movb %%dh,%2" \
  4744. ::"m" (*((addr)+2)), \
  4745. "m" (*((addr)+4)), \
  4746. "m" (*((addr)+7)), \
  4747. "d" (base) \
  4748. :"dx")
  4749.  
  4750. #define _set_limit(addr,limit) \
  4751. __asm__("movw %%dx,%0\n\t" \
  4752. "rorl $16,%%edx\n\t" \
  4753. "movb %1,%%dh\n\t" \
  4754. "andb $0xf0,%%dh\n\t" \
  4755. "orb %%dh,%%dl\n\t" \
  4756. "movb %%dl,%1" \
  4757. ::"m" (*(addr)), \
  4758. "m" (*((addr)+6)), \
  4759. "d" (limit) \
  4760. :"dx")
  4761.  
  4762. #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
  4763. #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
  4764.  
  4765. #define _get_base(addr) ({\
  4766. unsigned long __base; \
  4767. __asm__("movb %3,%%dh\n\t" \
  4768. "movb %2,%%dl\n\t" \
  4769. "shll $16,%%edx\n\t" \
  4770. "movw %1,%%dx" \
  4771. :"=d" (__base) \
  4772. :"m" (*((addr)+2)), \
  4773. "m" (*((addr)+4)), \
  4774. "m" (*((addr)+7))); \
  4775. __base;})
  4776.  
  4777. #define get_base(ldt) _get_base( ((char *)&(ldt)) )
  4778.  
  4779. #define get_limit(segment) ({ \
  4780. unsigned long __limit; \
  4781. __asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \
  4782. __limit;})
  4783.  
  4784. #endif
  4785.  
  4786. ------------------------------------------------------------------------
  4787.  
  4788. include/linux/sys.h
  4789.  
  4790. extern int sys_setup();
  4791. extern int sys_exit();
  4792. extern int sys_fork();
  4793. extern int sys_read();
  4794. extern int sys_write();
  4795. extern int sys_open();
  4796. extern int sys_close();
  4797. extern int sys_waitpid();
  4798. extern int sys_creat();
  4799. extern int sys_link();
  4800. extern int sys_unlink();
  4801. extern int sys_execve();
  4802. extern int sys_chdir();
  4803. extern int sys_time();
  4804. extern int sys_mknod();
  4805. extern int sys_chmod();
  4806. extern int sys_chown();
  4807. extern int sys_break();
  4808. extern int sys_stat();
  4809. extern int sys_lseek();
  4810. extern int sys_getpid();
  4811. extern int sys_mount();
  4812. extern int sys_umount();
  4813. extern int sys_setuid();
  4814. extern int sys_getuid();
  4815. extern int sys_stime();
  4816. extern int sys_ptrace();
  4817. extern int sys_alarm();
  4818. extern int sys_fstat();
  4819. extern int sys_pause();
  4820. extern int sys_utime();
  4821. extern int sys_stty();
  4822. extern int sys_gtty();
  4823. extern int sys_access();
  4824. extern int sys_nice();
  4825. extern int sys_ftime();
  4826. extern int sys_sync();
  4827. extern int sys_kill();
  4828. extern int sys_rename();
  4829. extern int sys_mkdir();
  4830. extern int sys_rmdir();
  4831. extern int sys_dup();
  4832. extern int sys_pipe();
  4833. extern int sys_times();
  4834. extern int sys_prof();
  4835. extern int sys_brk();
  4836. extern int sys_setgid();
  4837. extern int sys_getgid();
  4838. extern int sys_signal();
  4839. extern int sys_geteuid();
  4840. extern int sys_getegid();
  4841. extern int sys_acct();
  4842. extern int sys_phys();
  4843. extern int sys_lock();
  4844. extern int sys_ioctl();
  4845. extern int sys_fcntl();
  4846. extern int sys_mpx();
  4847. extern int sys_setpgid();
  4848. extern int sys_ulimit();
  4849. extern int sys_uname();
  4850. extern int sys_umask();
  4851. extern int sys_chroot();
  4852. extern int sys_ustat();
  4853. extern int sys_dup2();
  4854. extern int sys_getppid();
  4855. extern int sys_getpgrp();
  4856. extern int sys_setsid();
  4857.  
  4858. fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
  4859. sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
  4860. sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
  4861. sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
  4862. sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
  4863. sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
  4864. sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
  4865. sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
  4866. sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
  4867. sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
  4868. sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
  4869. sys_getpgrp,sys_setsid};
  4870.  
  4871. ------------------------------------------------------------------------
  4872.  
  4873. include/linux/tty.h
  4874.  
  4875. /*
  4876. * 'tty.h' defines some structures used by tty_io.c and some defines.
  4877. *
  4878. * NOTE! Don't touch this without checking that nothing in rs_io.s or
  4879. * con_io.s breaks. Some constants are hardwired into the system (mainly
  4880. * offsets into 'tty_queue'
  4881. */
  4882.  
  4883. #ifndef _TTY_H
  4884. #define _TTY_H
  4885.  
  4886. #include <termios.h>
  4887.  
  4888. #define TTY_BUF_SIZE 1024
  4889.  
  4890. struct tty_queue {
  4891. unsigned long data;
  4892. unsigned long head;
  4893. unsigned long tail;
  4894. struct task_struct * proc_list;
  4895. char buf[TTY_BUF_SIZE];
  4896. };
  4897.  
  4898. #define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1))
  4899. #define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1))
  4900. #define EMPTY(a) ((a).head == (a).tail)
  4901. #define LEFT(a) (((a).tail-(a).head-1)&(TTY_BUF_SIZE-1))
  4902. #define LAST(a) ((a).buf[(TTY_BUF_SIZE-1)&((a).head-1)])
  4903. #define FULL(a) (!LEFT(a))
  4904. #define CHARS(a) (((a).head-(a).tail)&(TTY_BUF_SIZE-1))
  4905. #define GETCH(queue,c) \
  4906. (void)({c=(queue).buf[(queue).tail];INC((queue).tail);})
  4907. #define PUTCH(c,queue) \
  4908. (void)({(queue).buf[(queue).head]=(c);INC((queue).head);})
  4909.  
  4910. #define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF])
  4911. #define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
  4912. #define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP])
  4913. #define START_CHAR(tty) ((tty)->termios.c_cc[VSTART])
  4914. #define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
  4915.  
  4916. struct tty_struct {
  4917. struct termios termios;
  4918. int pgrp;
  4919. int stopped;
  4920. void (*write)(struct tty_struct * tty);
  4921. struct tty_queue read_q;
  4922. struct tty_queue write_q;
  4923. struct tty_queue secondary;
  4924. };
  4925.  
  4926. extern struct tty_struct tty_table[];
  4927.  
  4928. /* intr=^C quit=^| erase=del kill=^U
  4929. eof=^D vtime=\0 vmin=\1 sxtc=\0
  4930. start=^Q stop=^S susp=^Y eol=\0
  4931. reprint=^R discard=^U werase=^W lnext=^V
  4932. eol2=\0
  4933. */
  4934. #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\031\0\022\017\027\026\0"
  4935.  
  4936. void rs_init(void);
  4937. void con_init(void);
  4938. void tty_init(void);
  4939.  
  4940. int tty_read(unsigned c, char * buf, int n);
  4941. int tty_write(unsigned c, char * buf, int n);
  4942.  
  4943. void rs_write(struct tty_struct * tty);
  4944. void con_write(struct tty_struct * tty);
  4945.  
  4946. void copy_to_cooked(struct tty_struct * tty);
  4947.  
  4948. #endif
  4949.  
  4950. ------------------------------------------------------------------------
  4951.  
  4952. include/signal.h
  4953.  
  4954. #ifndef _SIGNAL_H
  4955. #define _SIGNAL_H
  4956.  
  4957. #include <sys/types.h>
  4958.  
  4959. typedef int sig_atomic_t;
  4960. typedef unsigned int sigset_t; /* 32 bits */
  4961.  
  4962. #define _NSIG 32
  4963. #define NSIG _NSIG
  4964.  
  4965. #define SIGHUP 1
  4966. #define SIGINT 2
  4967. #define SIGQUIT 3
  4968. #define SIGILL 4
  4969. #define SIGTRAP 5
  4970. #define SIGABRT 6
  4971. #define SIGIOT 6
  4972. #define SIGUNUSED 7
  4973. #define SIGFPE 8
  4974. #define SIGKILL 9
  4975. #define SIGUSR1 10
  4976. #define SIGSEGV 11
  4977. #define SIGUSR2 12
  4978. #define SIGPIPE 13
  4979. #define SIGALRM 14
  4980. #define SIGTERM 15
  4981. #define SIGSTKFLT 16
  4982. #define SIGCHLD 17
  4983. #define SIGCONT 18
  4984. #define SIGSTOP 19
  4985. #define SIGTSTP 20
  4986. #define SIGTTIN 21
  4987. #define SIGTTOU 22
  4988.  
  4989. /* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */
  4990. #define SA_NOCLDSTOP 1
  4991.  
  4992. #define SIG_BLOCK 0 /* for blocking signals */
  4993. #define SIG_UNBLOCK 1 /* for unblocking signals */
  4994. #define SIG_SETMASK 2 /* for setting the signal mask */
  4995.  
  4996. #define SIG_DFL ((void (*)(int))0) /* default signal handling */
  4997. #define SIG_IGN ((void (*)(int))1) /* ignore signal */
  4998.  
  4999. struct sigaction {
  5000. void (*sa_handler)(int);
  5001. sigset_t sa_mask;
  5002. int sa_flags;
  5003. };
  5004.  
  5005. void (*signal(int _sig, void (*_func)(int)))(int);
  5006. int raise(int sig);
  5007. int kill(pid_t pid, int sig);
  5008. int sigaddset(sigset_t *mask, int signo);
  5009. int sigdelset(sigset_t *mask, int signo);
  5010. int sigemptyset(sigset_t *mask);
  5011. int sigfillset(sigset_t *mask);
  5012. int sigismember(sigset_t *mask, int signo); /* 1 - is, 0 - not, -1 error */
  5013. int sigpending(sigset_t *set);
  5014. int sigprocmask(int how, sigset_t *set, sigset_t *oldset);
  5015. int sigsuspend(sigset_t *sigmask);
  5016. int sigaction(int sig, struct sigaction *act, struct sigaction *oldact);
  5017.  
  5018. #endif /* _SIGNAL_H */
  5019.  
  5020. ------------------------------------------------------------------------
  5021.  
  5022. include/stdarg.h
  5023.  
  5024. #ifndef _STDARG_H
  5025. #define _STDARG_H
  5026.  
  5027. typedef char *va_list;
  5028.  
  5029. /* Amount of space required in an argument list for an arg of type TYPE.
  5030. TYPE may alternatively be an expression whose type is used. */
  5031.  
  5032. #define __va_rounded_size(TYPE) \
  5033. (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
  5034.  
  5035. #ifndef __sparc__
  5036. #define va_start(AP, LASTARG) \
  5037. (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
  5038. #else
  5039. #define va_start(AP, LASTARG) \
  5040. (__builtin_saveregs (), \
  5041. AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
  5042. #endif
  5043.  
  5044. void va_end (va_list); /* Defined in gnulib */
  5045. #define va_end(AP)
  5046.  
  5047. #define va_arg(AP, TYPE) \
  5048. (AP += __va_rounded_size (TYPE), \
  5049. *((TYPE *) (AP - __va_rounded_size (TYPE))))
  5050.  
  5051. #endif /* _STDARG_H */
  5052.  
  5053. ------------------------------------------------------------------------
  5054.  
  5055. include/stddef.h
  5056.  
  5057. #ifndef _STDDEF_H
  5058. #define _STDDEF_H
  5059.  
  5060. #ifndef _PTRDIFF_T
  5061. #define _PTRDIFF_T
  5062. typedef long ptrdiff_t;
  5063. #endif
  5064.  
  5065. #ifndef _SIZE_T
  5066. #define _SIZE_T
  5067. typedef unsigned long size_t;
  5068. #endif
  5069.  
  5070. #undef NULL
  5071. #define NULL ((void *)0)
  5072.  
  5073. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  5074.  
  5075. #endif
  5076.  
  5077. ------------------------------------------------------------------------
  5078.  
  5079. include/string.h
  5080.  
  5081. #ifndef _STRING_H_
  5082. #define _STRING_H_
  5083.  
  5084. #ifndef NULL
  5085. #define NULL ((void *) 0)
  5086. #endif
  5087.  
  5088. #ifndef _SIZE_T
  5089. #define _SIZE_T
  5090. typedef unsigned int size_t;
  5091. #endif
  5092.  
  5093. extern char * strerror(int errno);
  5094.  
  5095. /*
  5096. * This string-include defines all string functions as inline
  5097. * functions. Use gcc. It also assumes ds=es=data space, this should be
  5098. * normal. Most of the string-functions are rather heavily hand-optimized,
  5099. * see especially strtok,strstr,str[c]spn. They should work, but are not
  5100. * very easy to understand. Everything is done entirely within the register
  5101. * set, making the functions fast and clean. String instructions have been
  5102. * used through-out, making for "slightly" unclear code :-)
  5103. *
  5104. * (C) 1991 Linus Torvalds
  5105. */
  5106.  
  5107. extern inline char * strcpy(char * dest,const char *src)
  5108. {
  5109. __asm__("cld\n"
  5110. "1:\tlodsb\n\t"
  5111. "stosb\n\t"
  5112. "testb %%al,%%al\n\t"
  5113. "jne 1b"
  5114. ::"S" (src),"D" (dest):"si","di","ax");
  5115. return dest;
  5116. }
  5117.  
  5118. extern inline char * strncpy(char * dest,const char *src,int count)
  5119. {
  5120. __asm__("cld\n"
  5121. "1:\tdecl %2\n\t"
  5122. "js 2f\n\t"
  5123. "lodsb\n\t"
  5124. "stosb\n\t"
  5125. "testb %%al,%%al\n\t"
  5126. "jne 1b\n\t"
  5127. "rep\n\t"
  5128. "stosb\n"
  5129. "2:"
  5130. ::"S" (src),"D" (dest),"c" (count):"si","di","ax","cx");
  5131. return dest;
  5132. }
  5133.  
  5134. extern inline char * strcat(char * dest,const char * src)
  5135. {
  5136. __asm__("cld\n\t"
  5137. "repne\n\t"
  5138. "scasb\n\t"
  5139. "decl %1\n"
  5140. "1:\tlodsb\n\t"
  5141. "stosb\n\t"
  5142. "testb %%al,%%al\n\t"
  5143. "jne 1b"
  5144. ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx");
  5145. return dest;
  5146. }
  5147.  
  5148. extern inline char * strncat(char * dest,const char * src,int count)
  5149. {
  5150. __asm__("cld\n\t"
  5151. "repne\n\t"
  5152. "scasb\n\t"
  5153. "decl %1\n\t"
  5154. "movl %4,%3\n"
  5155. "1:\tdecl %3\n\t"
  5156. "js 2f\n\t"
  5157. "lodsb\n\t"
  5158. "stosb\n\t"
  5159. "testb %%al,%%al\n\t"
  5160. "jne 1b\n"
  5161. "2:\txorl %2,%2\n\t"
  5162. "stosb"
  5163. ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count)
  5164. :"si","di","ax","cx");
  5165. return dest;
  5166. }
  5167.  
  5168. extern inline int strcmp(const char * cs,const char * ct)
  5169. {
  5170. register int __res __asm__("ax");
  5171. __asm__("cld\n"
  5172. "1:\tlodsb\n\t"
  5173. "scasb\n\t"
  5174. "jne 2f\n\t"
  5175. "testb %%al,%%al\n\t"
  5176. "jne 1b\n\t"
  5177. "xorl %%eax,%%eax\n\t"
  5178. "jmp 3f\n"
  5179. "2:\tmovl $1,%%eax\n\t"
  5180. "jl 3f\n\t"
  5181. "negl %%eax\n"
  5182. "3:"
  5183. :"=a" (__res):"D" (cs),"S" (ct):"si","di");
  5184. return __res;
  5185. }
  5186.  
  5187. extern inline int strncmp(const char * cs,const char * ct,int count)
  5188. {
  5189. register int __res __asm__("ax");
  5190. __asm__("cld\n"
  5191. "1:\tdecl %3\n\t"
  5192. "js 2f\n\t"
  5193. "lodsb\n\t"
  5194. "scasb\n\t"
  5195. "jne 3f\n\t"
  5196. "testb %%al,%%al\n\t"
  5197. "jne 1b\n"
  5198. "2:\txorl %%eax,%%eax\n\t"
  5199. "jmp 4f\n"
  5200. "3:\tmovl $1,%%eax\n\t"
  5201. "jl 4f\n\t"
  5202. "negl %%eax\n"
  5203. "4:"
  5204. :"=a" (__res):"D" (cs),"S" (ct),"c" (count):"si","di","cx");
  5205. return __res;
  5206. }
  5207.  
  5208. extern inline char * strchr(const char * s,char c)
  5209. {
  5210. register char * __res __asm__("ax");
  5211. __asm__("cld\n\t"
  5212. "movb %%al,%%ah\n"
  5213. "1:\tlodsb\n\t"
  5214. "cmpb %%ah,%%al\n\t"
  5215. "je 2f\n\t"
  5216. "testb %%al,%%al\n\t"
  5217. "jne 1b\n\t"
  5218. "movl $1,%1\n"
  5219. "2:\tmovl %1,%0\n\t"
  5220. "decl %0"
  5221. :"=a" (__res):"S" (s),"0" (c):"si");
  5222. return __res;
  5223. }
  5224.  
  5225. extern inline char * strrchr(const char * s,char c)
  5226. {
  5227. register char * __res __asm__("dx");
  5228. __asm__("cld\n\t"
  5229. "movb %%al,%%ah\n"
  5230. "1:\tlodsb\n\t"
  5231. "cmpb %%ah,%%al\n\t"
  5232. "jne 2f\n\t"
  5233. "movl %%esi,%0\n\t"
  5234. "decl %0\n"
  5235. "2:\ttestb %%al,%%al\n\t"
  5236. "jne 1b"
  5237. :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si");
  5238. return __res;
  5239. }
  5240.  
  5241. extern inline int strspn(const char * cs, const char * ct)
  5242. {
  5243. register char * __res __asm__("si");
  5244. __asm__("cld\n\t"
  5245. "movl %4,%%edi\n\t"
  5246. "repne\n\t"
  5247. "scasb\n\t"
  5248. "notl %%ecx\n\t"
  5249. "decl %%ecx\n\t"
  5250. "movl %%ecx,%%edx\n"
  5251. "1:\tlodsb\n\t"
  5252. "testb %%al,%%al\n\t"
  5253. "je 2f\n\t"
  5254. "movl %4,%%edi\n\t"
  5255. "movl %%edx,%%ecx\n\t"
  5256. "repne\n\t"
  5257. "scasb\n\t"
  5258. "je 1b\n"
  5259. "2:\tdecl %0"
  5260. :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
  5261. :"ax","cx","dx","di");
  5262. return __res-cs;
  5263. }
  5264.  
  5265. extern inline int strcspn(const char * cs, const char * ct)
  5266. {
  5267. register char * __res __asm__("si");
  5268. __asm__("cld\n\t"
  5269. "movl %4,%%edi\n\t"
  5270. "repne\n\t"
  5271. "scasb\n\t"
  5272. "notl %%ecx\n\t"
  5273. "decl %%ecx\n\t"
  5274. "movl %%ecx,%%edx\n"
  5275. "1:\tlodsb\n\t"
  5276. "testb %%al,%%al\n\t"
  5277. "je 2f\n\t"
  5278. "movl %4,%%edi\n\t"
  5279. "movl %%edx,%%ecx\n\t"
  5280. "repne\n\t"
  5281. "scasb\n\t"
  5282. "jne 1b\n"
  5283. "2:\tdecl %0"
  5284. :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
  5285. :"ax","cx","dx","di");
  5286. return __res-cs;
  5287. }
  5288.  
  5289. extern inline char * strpbrk(const char * cs,const char * ct)
  5290. {
  5291. register char * __res __asm__("si");
  5292. __asm__("cld\n\t"
  5293. "movl %4,%%edi\n\t"
  5294. "repne\n\t"
  5295. "scasb\n\t"
  5296. "notl %%ecx\n\t"
  5297. "decl %%ecx\n\t"
  5298. "movl %%ecx,%%edx\n"
  5299. "1:\tlodsb\n\t"
  5300. "testb %%al,%%al\n\t"
  5301. "je 2f\n\t"
  5302. "movl %4,%%edi\n\t"
  5303. "movl %%edx,%%ecx\n\t"
  5304. "repne\n\t"
  5305. "scasb\n\t"
  5306. "jne 1b\n\t"
  5307. "decl %0\n\t"
  5308. "jmp 3f\n"
  5309. "2:\txorl %0,%0\n"
  5310. "3:"
  5311. :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
  5312. :"ax","cx","dx","di");
  5313. return __res;
  5314. }
  5315.  
  5316. extern inline char * strstr(const char * cs,const char * ct)
  5317. {
  5318. register char * __res __asm__("ax");
  5319. __asm__("cld\n\t" \
  5320. "movl %4,%%edi\n\t"
  5321. "repne\n\t"
  5322. "scasb\n\t"
  5323. "notl %%ecx\n\t"
  5324. "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
  5325. "movl %%ecx,%%edx\n"
  5326. "1:\tmovl %4,%%edi\n\t"
  5327. "movl %%esi,%%eax\n\t"
  5328. "movl %%edx,%%ecx\n\t"
  5329. "repe\n\t"
  5330. "cmpsb\n\t"
  5331. "je 2f\n\t" /* also works for empty string, see above */
  5332. "xchgl %%eax,%%esi\n\t"
  5333. "incl %%esi\n\t"
  5334. "cmpb $0,-1(%%eax)\n\t"
  5335. "jne 1b\n\t"
  5336. "xorl %%eax,%%eax\n\t"
  5337. "2:"
  5338. :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
  5339. :"cx","dx","di","si");
  5340. return __res;
  5341. }
  5342.  
  5343. extern inline int strlen(const char * s)
  5344. {
  5345. register int __res __asm__("cx");
  5346. __asm__("cld\n\t"
  5347. "repne\n\t"
  5348. "scasb\n\t"
  5349. "notl %0\n\t"
  5350. "decl %0"
  5351. :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di");
  5352. return __res;
  5353. }
  5354.  
  5355. extern char * ___strtok;
  5356.  
  5357. extern inline char * strtok(char * s,const char * ct)
  5358. {
  5359. register char * __res __asm__("si");
  5360. __asm__("testl %1,%1\n\t"
  5361. "jne 1f\n\t"
  5362. "testl %0,%0\n\t"
  5363. "je 8f\n\t"
  5364. "movl %0,%1\n"
  5365. "1:\txorl %0,%0\n\t"
  5366. "movl $-1,%%ecx\n\t"
  5367. "xorl %%eax,%%eax\n\t"
  5368. "cld\n\t"
  5369. "movl %4,%%edi\n\t"
  5370. "repne\n\t"
  5371. "scasb\n\t"
  5372. "notl %%ecx\n\t"
  5373. "decl %%ecx\n\t"
  5374. "je 7f\n\t" /* empty delimeter-string */
  5375. "movl %%ecx,%%edx\n"
  5376. "2:\tlodsb\n\t"
  5377. "testb %%al,%%al\n\t"
  5378. "je 7f\n\t"
  5379. "movl %4,%%edi\n\t"
  5380. "movl %%edx,%%ecx\n\t"
  5381. "repne\n\t"
  5382. "scasb\n\t"
  5383. "je 2b\n\t"
  5384. "decl %1\n\t"
  5385. "cmpb $0,(%1)\n\t"
  5386. "je 7f\n\t"
  5387. "movl %1,%0\n"
  5388. "3:\tlodsb\n\t"
  5389. "testb %%al,%%al\n\t"
  5390. "je 5f\n\t"
  5391. "movl %4,%%edi\n\t"
  5392. "movl %%edx,%%ecx\n\t"
  5393. "repne\n\t"
  5394. "scasb\n\t"
  5395. "jne 3b\n\t"
  5396. "decl %1\n\t"
  5397. "cmpb $0,(%1)\n\t"
  5398. "je 5f\n\t"
  5399. "movb $0,(%1)\n\t"
  5400. "incl %1\n\t"
  5401. "jmp 6f\n"
  5402. "5:\txorl %1,%1\n"
  5403. "6:\tcmpb $0,(%0)\n\t"
  5404. "jne 7f\n\t"
  5405. "xorl %0,%0\n"
  5406. "7:\ttestl %0,%0\n\t"
  5407. "jne 8f\n\t"
  5408. "movl %0,%1\n"
  5409. "8:"
  5410. :"=b" (__res),"=S" (___strtok)
  5411. :"0" (___strtok),"1" (s),"g" (ct)
  5412. :"ax","cx","dx","di");
  5413. return __res;
  5414. }
  5415.  
  5416. extern inline void * memcpy(void * dest,const void * src, int n)
  5417. {
  5418. __asm__("cld\n\t"
  5419. "rep\n\t"
  5420. "movsb"
  5421. ::"c" (n),"S" (src),"D" (dest)
  5422. :"cx","si","di");
  5423. return dest;
  5424. }
  5425.  
  5426. extern inline void * memmove(void * dest,const void * src, int n)
  5427. {
  5428. if (dest<src)
  5429. __asm__("cld\n\t"
  5430. "rep\n\t"
  5431. "movsb"
  5432. ::"c" (n),"S" (src),"D" (dest)
  5433. :"cx","si","di");
  5434. else
  5435. __asm__("std\n\t"
  5436. "rep\n\t"
  5437. "movsb"
  5438. ::"c" (n),"S" (src+n-1),"D" (dest+n-1)
  5439. :"cx","si","di");
  5440. return dest;
  5441. }
  5442.  
  5443. extern inline int memcmp(const void * cs,const void * ct,int count)
  5444. {
  5445. register int __res __asm__("ax");
  5446. __asm__("cld\n\t"
  5447. "repe\n\t"
  5448. "cmpsb\n\t"
  5449. "je 1f\n\t"
  5450. "movl $1,%%eax\n\t"
  5451. "jl 1f\n\t"
  5452. "negl %%eax\n"
  5453. "1:"
  5454. :"=a" (__res):"0" (0),"D" (cs),"S" (ct),"c" (count)
  5455. :"si","di","cx");
  5456. return __res;
  5457. }
  5458.  
  5459. extern inline void * memchr(const void * cs,char c,int count)
  5460. {
  5461. register void * __res __asm__("di");
  5462. if (!count)
  5463. return NULL;
  5464. __asm__("cld\n\t"
  5465. "repne\n\t"
  5466. "scasb\n\t"
  5467. "je 1f\n\t"
  5468. "movl $1,%0\n"
  5469. "1:\tdecl %0"
  5470. :"=D" (__res):"a" (c),"D" (cs),"c" (count)
  5471. :"cx");
  5472. return __res;
  5473. }
  5474.  
  5475. extern inline void * memset(void * s,char c,int count)
  5476. {
  5477. __asm__("cld\n\t"
  5478. "rep\n\t"
  5479. "stosb"
  5480. ::"a" (c),"D" (s),"c" (count)
  5481. :"cx","di");
  5482. return s;
  5483. }
  5484.  
  5485. #endif
  5486.  
  5487. ------------------------------------------------------------------------
  5488.  
  5489. include/sys/stat.h
  5490.  
  5491. #ifndef _SYS_STAT_H
  5492. #define _SYS_STAT_H
  5493.  
  5494. #include <sys/types.h>
  5495.  
  5496. struct stat {
  5497. dev_t st_dev;
  5498. ino_t st_ino;
  5499. umode_t st_mode;
  5500. nlink_t st_nlink;
  5501. uid_t st_uid;
  5502. gid_t st_gid;
  5503. dev_t st_rdev;
  5504. off_t st_size;
  5505. time_t st_atime;
  5506. time_t st_mtime;
  5507. time_t st_ctime;
  5508. };
  5509.  
  5510. #define S_IFMT 00170000
  5511. #define S_IFREG 0100000
  5512. #define S_IFBLK 0060000
  5513. #define S_IFDIR 0040000
  5514. #define S_IFCHR 0020000
  5515. #define S_IFIFO 0010000
  5516. #define S_ISUID 0004000
  5517. #define S_ISGID 0002000
  5518. #define S_ISVTX 0001000
  5519.  
  5520. #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
  5521. #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
  5522. #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
  5523. #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
  5524. #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
  5525.  
  5526. #define S_IRWXU 00700
  5527. #define S_IRUSR 00400
  5528. #define S_IWUSR 00200
  5529. #define S_IXUSR 00100
  5530.  
  5531. #define S_IRWXG 00070
  5532. #define S_IRGRP 00040
  5533. #define S_IWGRP 00020
  5534. #define S_IXGRP 00010
  5535.  
  5536. #define S_IRWXO 00007
  5537. #define S_IROTH 00004
  5538. #define S_IWOTH 00002
  5539. #define S_IXOTH 00001
  5540.  
  5541. extern int chmod(const char *_path, mode_t mode);
  5542. extern int fstat(int fildes, struct stat *stat_buf);
  5543. extern int mkdir(const char *_path, mode_t mode);
  5544. extern int mkfifo(const char *_path, mode_t mode);
  5545. extern int stat(const char *filename, struct stat *stat_buf);
  5546. extern mode_t umask(mode_t mask);
  5547.  
  5548. #endif
  5549.  
  5550. ------------------------------------------------------------------------
  5551.  
  5552. include/sys/times.h
  5553.  
  5554. #ifndef _TIMES_H
  5555. #define _TIMES_H
  5556.  
  5557. #include <sys/types.h>
  5558.  
  5559. struct tms {
  5560. time_t tms_utime;
  5561. time_t tms_stime;
  5562. time_t tms_cutime;
  5563. time_t tms_cstime;
  5564. };
  5565.  
  5566. extern time_t times(struct tms * tp);
  5567.  
  5568. #endif
  5569.  
  5570. ------------------------------------------------------------------------
  5571.  
  5572. include/sys/types.h
  5573.  
  5574. #ifndef _SYS_TYPES_H
  5575. #define _SYS_TYPES_H
  5576.  
  5577. #ifndef _SIZE_T
  5578. #define _SIZE_T
  5579. typedef unsigned int size_t;
  5580. #endif
  5581.  
  5582. #ifndef _TIME_T
  5583. #define _TIME_T
  5584. typedef long time_t;
  5585. #endif
  5586.  
  5587. #ifndef _PTRDIFF_T
  5588. #define _PTRDIFF_T
  5589. typedef long ptrdiff_t;
  5590. #endif
  5591.  
  5592. #ifndef NULL
  5593. #define NULL ((void *) 0)
  5594. #endif
  5595.  
  5596. typedef int pid_t;
  5597. typedef unsigned short uid_t;
  5598. typedef unsigned char gid_t;
  5599. typedef unsigned short dev_t;
  5600. typedef unsigned short ino_t;
  5601. typedef unsigned short mode_t;
  5602. typedef unsigned short umode_t;
  5603. typedef unsigned char nlink_t;
  5604. typedef int daddr_t;
  5605. typedef long off_t;
  5606. typedef unsigned char u_char;
  5607. typedef unsigned short ushort;
  5608.  
  5609. typedef struct { int quot,rem; } div_t;
  5610. typedef struct { long quot,rem; } ldiv_t;
  5611.  
  5612. struct ustat {
  5613. daddr_t f_tfree;
  5614. ino_t f_tinode;
  5615. char f_fname[6];
  5616. char f_fpack[6];
  5617. };
  5618.  
  5619. #endif
  5620.  
  5621. ------------------------------------------------------------------------
  5622.  
  5623. include/sys/utsname.h
  5624.  
  5625. #ifndef _SYS_UTSNAME_H
  5626. #define _SYS_UTSNAME_H
  5627.  
  5628. #include <sys/types.h>
  5629.  
  5630. struct utsname {
  5631. char sysname[9];
  5632. char nodename[9];
  5633. char release[9];
  5634. char version[9];
  5635. char machine[9];
  5636. };
  5637.  
  5638. extern int uname(struct utsname * utsbuf);
  5639.  
  5640. #endif
  5641.  
  5642. ------------------------------------------------------------------------
  5643.  
  5644. include/sys/wait.h
  5645.  
  5646. #ifndef _SYS_WAIT_H
  5647. #define _SYS_WAIT_H
  5648.  
  5649. #include <sys/types.h>
  5650.  
  5651. #define _LOW(v) ( (v) & 0377)
  5652. #define _HIGH(v) ( ((v) >> 8) & 0377)
  5653.  
  5654. /* options for waitpid, WUNTRACED not supported */
  5655. #define WNOHANG 1
  5656. #define WUNTRACED 2
  5657.  
  5658. #define WIFEXITED(s) (!((s)&0xFF)
  5659. #define WIFSTOPPED(s) (((s)&0xFF)==0x7F)
  5660. #define WEXITSTATUS(s) (((s)>>8)&0xFF)
  5661. #define WTERMSIG(s) ((s)&0x7F)
  5662. #define WSTOPSIG(s) (((s)>>8)&0xFF)
  5663. #define WIFSIGNALED(s) (((unsigned int)(s)-1 & 0xFFFF) < 0xFF)
  5664.  
  5665. pid_t wait(int *stat_loc);
  5666. pid_t waitpid(pid_t pid, int *stat_loc, int options);
  5667.  
  5668. #endif
  5669.  
  5670. ------------------------------------------------------------------------
  5671.  
  5672. include/termios.h
  5673.  
  5674. #ifndef _TERMIOS_H
  5675. #define _TERMIOS_H
  5676.  
  5677. #define TTY_BUF_SIZE 1024
  5678.  
  5679. /* 0x54 is just a magic number to make these relatively uniqe ('T') */
  5680.  
  5681. #define TCGETS 0x5401
  5682. #define TCSETS 0x5402
  5683. #define TCSETSW 0x5403
  5684. #define TCSETSF 0x5404
  5685. #define TCGETA 0x5405
  5686. #define TCSETA 0x5406
  5687. #define TCSETAW 0x5407
  5688. #define TCSETAF 0x5408
  5689. #define TCSBRK 0x5409
  5690. #define TCXONC 0x540A
  5691. #define TCFLSH 0x540B
  5692. #define TIOCEXCL 0x540C
  5693. #define TIOCNXCL 0x540D
  5694. #define TIOCSCTTY 0x540E
  5695. #define TIOCGPGRP 0x540F
  5696. #define TIOCSPGRP 0x5410
  5697. #define TIOCOUTQ 0x5411
  5698. #define TIOCSTI 0x5412
  5699. #define TIOCGWINSZ 0x5413
  5700. #define TIOCSWINSZ 0x5414
  5701. #define TIOCMGET 0x5415
  5702. #define TIOCMBIS 0x5416
  5703. #define TIOCMBIC 0x5417
  5704. #define TIOCMSET 0x5418
  5705. #define TIOCGSOFTCAR 0x5419
  5706. #define TIOCSSOFTCAR 0x541A
  5707.  
  5708. struct winsize {
  5709. unsigned short ws_row;
  5710. unsigned short ws_col;
  5711. unsigned short ws_xpixel;
  5712. unsigned short ws_ypixel;
  5713. };
  5714.  
  5715. #define NCC 8
  5716. struct termio {
  5717. unsigned short c_iflag; /* input mode flags */
  5718. unsigned short c_oflag; /* output mode flags */
  5719. unsigned short c_cflag; /* control mode flags */
  5720. unsigned short c_lflag; /* local mode flags */
  5721. unsigned char c_line; /* line discipline */
  5722. unsigned char c_cc[NCC]; /* control characters */
  5723. };
  5724.  
  5725. #define NCCS 17
  5726. struct termios {
  5727. unsigned long c_iflag; /* input mode flags */
  5728. unsigned long c_oflag; /* output mode flags */
  5729. unsigned long c_cflag; /* control mode flags */
  5730. unsigned long c_lflag; /* local mode flags */
  5731. unsigned char c_line; /* line discipline */
  5732. unsigned char c_cc[NCCS]; /* control characters */
  5733. };
  5734.  
  5735. /* c_cc characters */
  5736. #define VINTR 0
  5737. #define VQUIT 1
  5738. #define VERASE 2
  5739. #define VKILL 3
  5740. #define VEOF 4
  5741. #define VTIME 5
  5742. #define VMIN 6
  5743. #define VSWTC 7
  5744. #define VSTART 8
  5745. #define VSTOP 9
  5746. #define VSUSP 10
  5747. #define VEOL 11
  5748. #define VREPRINT 12
  5749. #define VDISCARD 13
  5750. #define VWERASE 14
  5751. #define VLNEXT 15
  5752. #define VEOL2 16
  5753.  
  5754. /* c_iflag bits */
  5755. #define IGNBRK 0000001
  5756. #define BRKINT 0000002
  5757. #define IGNPAR 0000004
  5758. #define PARMRK 0000010
  5759. #define INPCK 0000020
  5760. #define ISTRIP 0000040
  5761. #define INLCR 0000100
  5762. #define IGNCR 0000200
  5763. #define ICRNL 0000400
  5764. #define IUCLC 0001000
  5765. #define IXON 0002000
  5766. #define IXANY 0004000
  5767. #define IXOFF 0010000
  5768. #define IMAXBEL 0020000
  5769.  
  5770. /* c_oflag bits */
  5771. #define OPOST 0000001
  5772. #define OLCUC 0000002
  5773. #define ONLCR 0000004
  5774. #define OCRNL 0000010
  5775. #define ONOCR 0000020
  5776. #define ONLRET 0000040
  5777. #define OFILL 0000100
  5778. #define OFDEL 0000200
  5779. #define NLDLY 0000400
  5780. #define NL0 0000000
  5781. #define NL1 0000400
  5782. #define CRDLY 0003000
  5783. #define CR0 0000000
  5784. #define CR1 0001000
  5785. #define CR2 0002000
  5786. #define CR3 0003000
  5787. #define TABDLY 0014000
  5788. #define TAB0 0000000
  5789. #define TAB1 0004000
  5790. #define TAB2 0010000
  5791. #define TAB3 0014000
  5792. #define XTABS 0014000
  5793. #define BSDLY 0020000
  5794. #define BS0 0000000
  5795. #define BS1 0020000
  5796. #define VTDLY 0040000
  5797. #define VT0 0000000
  5798. #define VT1 0040000
  5799. #define FFDLY 0040000
  5800. #define FF0 0000000
  5801. #define FF1 0040000
  5802.  
  5803. /* c_cflag bit meaning */
  5804. #define CBAUD 0000017
  5805. #define B0 0000000 /* hang up */
  5806. #define B50 0000001
  5807. #define B75 0000002
  5808. #define B110 0000003
  5809. #define B134 0000004
  5810. #define B150 0000005
  5811. #define B200 0000006
  5812. #define B300 0000007
  5813. #define B600 0000010
  5814. #define B1200 0000011
  5815. #define B1800 0000012
  5816. #define B2400 0000013
  5817. #define B4800 0000014
  5818. #define B9600 0000015
  5819. #define B19200 0000016
  5820. #define B38400 0000017
  5821. #define CSIZE 0000060
  5822. #define CS5 0000000
  5823. #define CS6 0000020
  5824. #define CS7 0000040
  5825. #define CS8 0000060
  5826. #define CSTOPB 0000100
  5827. #define CREAD 0000200
  5828. #define CPARENB 0000400
  5829. #define CPARODD 0001000
  5830. #define HUPCL 0002000
  5831. #define CLOCAL 0004000
  5832. #define CIBAUD 03600000 /* input baud rate (not used) */
  5833. #define CRTSCTS 020000000000 /* flow control */
  5834.  
  5835. /* c_lflag bits */
  5836. #define ISIG 0000001
  5837. #define ICANON 0000002
  5838. #define XCASE 0000004
  5839. #define ECHO 0000010
  5840. #define ECHOE 0000020
  5841. #define ECHOK 0000040
  5842. #define ECHONL 0000100
  5843. #define NOFLSH 0000200
  5844. #define TOSTOP 0000400
  5845. #define ECHOCTL 0001000
  5846. #define ECHOPRT 0002000
  5847. #define ECHOKE 0004000
  5848. #define FLUSHO 0010000
  5849. #define PENDIN 0040000
  5850. #define IEXTEN 0100000
  5851.  
  5852. /* modem lines */
  5853. #define TIOCM_LE 0x001
  5854. #define TIOCM_DTR 0x002
  5855. #define TIOCM_RTS 0x004
  5856. #define TIOCM_ST 0x008
  5857. #define TIOCM_SR 0x010
  5858. #define TIOCM_CTS 0x020
  5859. #define TIOCM_CAR 0x040
  5860. #define TIOCM_RNG 0x080
  5861. #define TIOCM_DSR 0x100
  5862. #define TIOCM_CD TIOCM_CAR
  5863. #define TIOCM_RI TIOCM_RNG
  5864.  
  5865. /* tcflow() and TCXONC use these */
  5866. #define TCOOFF 0
  5867. #define TCOON 1
  5868. #define TCIOFF 2
  5869. #define TCION 3
  5870.  
  5871. /* tcflush() and TCFLSH use these */
  5872. #define TCIFLUSH 0
  5873. #define TCOFLUSH 1
  5874. #define TCIOFLUSH 2
  5875.  
  5876. /* tcsetattr uses these */
  5877. #define TCSANOW 0
  5878. #define TCSADRAIN 1
  5879. #define TCSAFLUSH 2
  5880.  
  5881. typedef int speed_t;
  5882.  
  5883. extern speed_t cfgetispeed(struct termios *termios_p);
  5884. extern speed_t cfgetospeed(struct termios *termios_p);
  5885. extern int cfsetispeed(struct termios *termios_p, speed_t speed);
  5886. extern int cfsetospeed(struct termios *termios_p, speed_t speed);
  5887. extern int tcdrain(int fildes);
  5888. extern int tcflow(int fildes, int action);
  5889. extern int tcflush(int fildes, int queue_selector);
  5890. extern int tcgetattr(int fildes, struct termios *termios_p);
  5891. extern int tcsendbreak(int fildes, int duration);
  5892. extern int tcsetattr(int fildes, int optional_actions,
  5893. struct termios *termios_p);
  5894.  
  5895. #endif
  5896.  
  5897. ------------------------------------------------------------------------
  5898.  
  5899. include/time.h
  5900.  
  5901. #ifndef _TIME_H
  5902. #define _TIME_H
  5903.  
  5904. #ifndef _TIME_T
  5905. #define _TIME_T
  5906. typedef long time_t;
  5907. #endif
  5908.  
  5909. #ifndef _SIZE_T
  5910. #define _SIZE_T
  5911. typedef unsigned int size_t;
  5912. #endif
  5913.  
  5914. #define CLOCKS_PER_SEC 100
  5915.  
  5916. typedef long clock_t;
  5917.  
  5918. struct tm {
  5919. int tm_sec;
  5920. int tm_min;
  5921. int tm_hour;
  5922. int tm_mday;
  5923. int tm_mon;
  5924. int tm_year;
  5925. int tm_wday;
  5926. int tm_yday;
  5927. int tm_isdst;
  5928. };
  5929.  
  5930. clock_t clock(void);
  5931. time_t time(time_t * tp);
  5932. double difftime(time_t time2, time_t time1);
  5933. time_t mktime(struct tm * tp);
  5934.  
  5935. char * asctime(const struct tm * tp);
  5936. char * ctime(const time_t * tp);
  5937. struct tm * gmtime(const time_t *tp);
  5938. struct tm *localtime(const time_t * tp);
  5939. size_t strftime(char * s, size_t smax, const char * fmt, const struct tm * tp);
  5940. void tzset(void);
  5941.  
  5942. #endif
  5943.  
  5944. ------------------------------------------------------------------------
  5945.  
  5946. include/unistd.h
  5947.  
  5948. #ifndef _UNISTD_H
  5949. #define _UNISTD_H
  5950.  
  5951. /* ok, this may be a joke, but I'm working on it */
  5952. #define _POSIX_VERSION 198808L
  5953.  
  5954. #define _POSIX_CHOWN_RESTRICTED /* only root can do a chown (I think..) */
  5955. /* #define _POSIX_NO_TRUNC*/ /* pathname truncation (but see in kernel) */
  5956. #define _POSIX_VDISABLE '\0' /* character to disable things like ^C */
  5957. /*#define _POSIX_SAVED_IDS */ /* we'll get to this yet */
  5958. /*#define _POSIX_JOB_CONTROL */ /* we aren't there quite yet. Soon hopefully */
  5959.  
  5960. #define STDIN_FILENO 0
  5961. #define STDOUT_FILENO 1
  5962. #define STDERR_FILENO 2
  5963.  
  5964. #ifndef NULL
  5965. #define NULL ((void *)0)
  5966. #endif
  5967.  
  5968. /* access */
  5969. #define F_OK 0
  5970. #define X_OK 1
  5971. #define W_OK 2
  5972. #define R_OK 4
  5973.  
  5974. /* lseek */
  5975. #define SEEK_SET 0
  5976. #define SEEK_CUR 1
  5977. #define SEEK_END 2
  5978.  
  5979. /* _SC stands for System Configuration. We don't use them much */
  5980. #define _SC_ARG_MAX 1
  5981. #define _SC_CHILD_MAX 2
  5982. #define _SC_CLOCKS_PER_SEC 3
  5983. #define _SC_NGROUPS_MAX 4
  5984. #define _SC_OPEN_MAX 5
  5985. #define _SC_JOB_CONTROL 6
  5986. #define _SC_SAVED_IDS 7
  5987. #define _SC_VERSION 8
  5988.  
  5989. /* more (possibly) configurable things - now pathnames */
  5990. #define _PC_LINK_MAX 1
  5991. #define _PC_MAX_CANON 2
  5992. #define _PC_MAX_INPUT 3
  5993. #define _PC_NAME_MAX 4
  5994. #define _PC_PATH_MAX 5
  5995. #define _PC_PIPE_BUF 6
  5996. #define _PC_NO_TRUNC 7
  5997. #define _PC_VDISABLE 8
  5998. #define _PC_CHOWN_RESTRICTED 9
  5999.  
  6000. #include <sys/stat.h>
  6001. #include <sys/times.h>
  6002. #include <sys/utsname.h>
  6003. #include <utime.h>
  6004.  
  6005. #ifdef __LIBRARY__
  6006.  
  6007. #define __NR_setup 0 /* used only by init, to get system going */
  6008. #define __NR_exit 1
  6009. #define __NR_fork 2
  6010. #define __NR_read 3
  6011. #define __NR_write 4
  6012. #define __NR_open 5
  6013. #define __NR_close 6
  6014. #define __NR_waitpid 7
  6015. #define __NR_creat 8
  6016. #define __NR_link 9
  6017. #define __NR_unlink 10
  6018. #define __NR_execve 11
  6019. #define __NR_chdir 12
  6020. #define __NR_time 13
  6021. #define __NR_mknod 14
  6022. #define __NR_chmod 15
  6023. #define __NR_chown 16
  6024. #define __NR_break 17
  6025. #define __NR_stat 18
  6026. #define __NR_lseek 19
  6027. #define __NR_getpid 20
  6028. #define __NR_mount 21
  6029. #define __NR_umount 22
  6030. #define __NR_setuid 23
  6031. #define __NR_getuid 24
  6032. #define __NR_stime 25
  6033. #define __NR_ptrace 26
  6034. #define __NR_alarm 27
  6035. #define __NR_fstat 28
  6036. #define __NR_pause 29
  6037. #define __NR_utime 30
  6038. #define __NR_stty 31
  6039. #define __NR_gtty 32
  6040. #define __NR_access 33
  6041. #define __NR_nice 34
  6042. #define __NR_ftime 35
  6043. #define __NR_sync 36
  6044. #define __NR_kill 37
  6045. #define __NR_rename 38
  6046. #define __NR_mkdir 39
  6047. #define __NR_rmdir 40
  6048. #define __NR_dup 41
  6049. #define __NR_pipe 42
  6050. #define __NR_times 43
  6051. #define __NR_prof 44
  6052. #define __NR_brk 45
  6053. #define __NR_setgid 46
  6054. #define __NR_getgid 47
  6055. #define __NR_signal 48
  6056. #define __NR_geteuid 49
  6057. #define __NR_getegid 50
  6058. #define __NR_acct 51
  6059. #define __NR_phys 52
  6060. #define __NR_lock 53
  6061. #define __NR_ioctl 54
  6062. #define __NR_fcntl 55
  6063. #define __NR_mpx 56
  6064. #define __NR_setpgid 57
  6065. #define __NR_ulimit 58
  6066. #define __NR_uname 59
  6067. #define __NR_umask 60
  6068. #define __NR_chroot 61
  6069. #define __NR_ustat 62
  6070. #define __NR_dup2 63
  6071. #define __NR_getppid 64
  6072. #define __NR_getpgrp 65
  6073. #define __NR_setsid 66
  6074.  
  6075. #define _syscall0(type,name) \
  6076. type name(void) \
  6077. { \
  6078. type __res; \
  6079. __asm__ volatile ("int $0x80" \
  6080. : "=a" (__res) \
  6081. : "0" (__NR_##name)); \
  6082. if (__res >= 0) \
  6083. return __res; \
  6084. errno = -__res; \
  6085. return -1; \
  6086. }
  6087.  
  6088. #define _syscall1(type,name,atype,a) \
  6089. type name(atype a) \
  6090. { \
  6091. type __res; \
  6092. __asm__ volatile ("int $0x80" \
  6093. : "=a" (__res) \
  6094. : "0" (__NR_##name),"b" (a)); \
  6095. if (__res >= 0) \
  6096. return __res; \
  6097. errno = -__res; \
  6098. return -1; \
  6099. }
  6100.  
  6101. #define _syscall2(type,name,atype,a,btype,b) \
  6102. type name(atype a,btype b) \
  6103. { \
  6104. type __res; \
  6105. __asm__ volatile ("int $0x80" \
  6106. : "=a" (__res) \
  6107. : "0" (__NR_##name),"b" (a),"c" (b)); \
  6108. if (__res >= 0) \
  6109. return __res; \
  6110. errno = -__res; \
  6111. return -1; \
  6112. }
  6113.  
  6114. #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
  6115. type name(atype a,btype b,ctype c) \
  6116. { \
  6117. type __res; \
  6118. __asm__ volatile ("int $0x80" \
  6119. : "=a" (__res) \
  6120. : "0" (__NR_##name),"b" (a),"c" (b),"d" (c)); \
  6121. if (__res<0) \
  6122. errno=-__res , __res = -1; \
  6123. return __res;\
  6124. }
  6125.  
  6126. #endif /* __LIBRARY__ */
  6127.  
  6128. extern int errno;
  6129.  
  6130. int access(const char * filename, mode_t mode);
  6131. int acct(const char * filename);
  6132. int alarm(int sec);
  6133. int brk(void * end_data_segment);
  6134. void * sbrk(ptrdiff_t increment);
  6135. int chdir(const char * filename);
  6136. int chmod(const char * filename, mode_t mode);
  6137. int chown(const char * filename, uid_t owner, gid_t group);
  6138. int chroot(const char * filename);
  6139. int close(int fildes);
  6140. int creat(const char * filename, mode_t mode);
  6141. int dup(int fildes);
  6142. int execve(const char * filename, char ** argv, char ** envp);
  6143. int execv(const char * pathname, char ** argv);
  6144. int execvp(const char * file, char ** argv);
  6145. int execl(const char * pathname, char * arg0, ...);
  6146. int execlp(const char * file, char * arg0, ...);
  6147. int execle(const char * pathname, char * arg0, ...);
  6148. volatile void exit(int status);
  6149. volatile void _exit(int status);
  6150. int fcntl(int fildes, int cmd, ...);
  6151. int fork(void);
  6152. int getpid(void);
  6153. int getuid(void);
  6154. int geteuid(void);
  6155. int getgid(void);
  6156. int getegid(void);
  6157. int ioctl(int fildes, int cmd, ...);
  6158. int kill(pid_t pid, int signal);
  6159. int link(const char * filename1, const char * filename2);
  6160. int lseek(int fildes, off_t offset, int origin);
  6161. int mknod(const char * filename, mode_t mode, dev_t dev);
  6162. int mount(const char * specialfile, const char * dir, int rwflag);
  6163. int nice(int val);
  6164. int open(const char * filename, int flag, ...);
  6165. int pause(void);
  6166. int pipe(int * fildes);
  6167. int read(int fildes, char * buf, off_t count);
  6168. int setpgrp(void);
  6169. int setpgid(pid_t pid,pid_t pgid);
  6170. int setuid(uid_t uid);
  6171. int setgid(gid_t gid);
  6172. void (*signal(int sig, void (*fn)(int)))(int);
  6173. int stat(const char * filename, struct stat * stat_buf);
  6174. int fstat(int fildes, struct stat * stat_buf);
  6175. int stime(time_t * tptr);
  6176. int sync(void);
  6177. time_t time(time_t * tloc);
  6178. time_t times(struct tms * tbuf);
  6179. int ulimit(int cmd, long limit);
  6180. mode_t umask(mode_t mask);
  6181. int umount(const char * specialfile);
  6182. int uname(struct utsname * name);
  6183. int unlink(const char * filename);
  6184. int ustat(dev_t dev, struct ustat * ubuf);
  6185. int utime(const char * filename, struct utimbuf * times);
  6186. pid_t waitpid(pid_t pid,int * wait_stat,int options);
  6187. pid_t wait(int * wait_stat);
  6188. int write(int fildes, const char * buf, off_t count);
  6189. int dup2(int oldfd, int newfd);
  6190. int getppid(void);
  6191. pid_t getpgrp(void);
  6192. pid_t setsid(void);
  6193.  
  6194. #endif
  6195.  
  6196. ------------------------------------------------------------------------
  6197.  
  6198. include/utime.h
  6199.  
  6200. #ifndef _UTIME_H
  6201. #define _UTIME_H
  6202.  
  6203. #include <sys/types.h> /* I know - shouldn't do this, but .. */
  6204.  
  6205. struct utimbuf {
  6206. time_t actime;
  6207. time_t modtime;
  6208. };
  6209.  
  6210. extern int utime(const char *filename, struct utimbuf *times);
  6211.  
  6212. #endif
  6213.  
  6214. ------------------------------------------------------------------------
  6215.  
  6216. init/main.c
  6217.  
  6218. #define __LIBRARY__
  6219. #include <unistd.h>
  6220. #include <time.h>
  6221.  
  6222. /*
  6223. * we need this inline - forking from kernel space will result
  6224. * in NO COPY ON WRITE (!!!), until an execve is executed. This
  6225. * is no problem, but for the stack. This is handled by not letting
  6226. * main() use the stack at all after fork(). Thus, no function
  6227. * calls - which means inline code for fork too, as otherwise we
  6228. * would use the stack upon exit from 'fork()'.
  6229. *
  6230. * Actually only pause and fork are needed inline, so that there
  6231. * won't be any messing with the stack from main(), but we define
  6232. * some others too.
  6233. */
  6234. static inline _syscall0(int,fork)
  6235. static inline _syscall0(int,pause)
  6236. static inline _syscall0(int,setup)
  6237. static inline _syscall0(int,sync)
  6238.  
  6239. #include <linux/tty.h>
  6240. #include <linux/sched.h>
  6241. #include <linux/head.h>
  6242. #include <asm/system.h>
  6243. #include <asm/io.h>
  6244.  
  6245. #include <stddef.h>
  6246. #include <stdarg.h>
  6247. #include <unistd.h>
  6248. #include <fcntl.h>
  6249. #include <sys/types.h>
  6250.  
  6251. #include <linux/fs.h>
  6252.  
  6253. static char printbuf[1024];
  6254.  
  6255. extern int vsprintf();
  6256. extern void init(void);
  6257. extern void hd_init(void);
  6258. extern long kernel_mktime(struct tm * tm);
  6259. extern long startup_time;
  6260.  
  6261. /*
  6262. * Yeah, yeah, it's ugly, but I cannot find how to do this correctly
  6263. * and this seems to work. I anybody has more info on the real-time
  6264. * clock I'd be interested. Most of this was trial and error, and some
  6265. * bios-listing reading. Urghh.
  6266. */
  6267.  
  6268. #define CMOS_READ(addr) ({ \
  6269. outb_p(0x80|addr,0x70); \
  6270. inb_p(0x71); \
  6271. })
  6272.  
  6273. #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
  6274.  
  6275. static void time_init(void)
  6276. {
  6277. struct tm time;
  6278.  
  6279. do {
  6280. time.tm_sec = CMOS_READ(0);
  6281. time.tm_min = CMOS_READ(2);
  6282. time.tm_hour = CMOS_READ(4);
  6283. time.tm_mday = CMOS_READ(7);
  6284. time.tm_mon = CMOS_READ(8)-1;
  6285. time.tm_year = CMOS_READ(9);
  6286. } while (time.tm_sec != CMOS_READ(0));
  6287. BCD_TO_BIN(time.tm_sec);
  6288. BCD_TO_BIN(time.tm_min);
  6289. BCD_TO_BIN(time.tm_hour);
  6290. BCD_TO_BIN(time.tm_mday);
  6291. BCD_TO_BIN(time.tm_mon);
  6292. BCD_TO_BIN(time.tm_year);
  6293. startup_time = kernel_mktime(&time);
  6294. }
  6295.  
  6296. void main(void) /* This really IS void, no error here. */
  6297. { /* The startup routine assumes (well, ...) this */
  6298. /*
  6299. * Interrupts are still disabled. Do necessary setups, then
  6300. * enable them
  6301. */
  6302. time_init();
  6303. tty_init();
  6304. trap_init();
  6305. sched_init();
  6306. buffer_init();
  6307. hd_init();
  6308. sti();
  6309. move_to_user_mode();
  6310. if (!fork()) { /* we count on this going ok */
  6311. init();
  6312. }
  6313. /*
  6314. * NOTE!! For any other task 'pause()' would mean we have to get a
  6315. * signal to awaken, but task0 is the sole exception (see 'schedule()')
  6316. * as task 0 gets activated at every idle moment (when no other tasks
  6317. * can run). For task0 'pause()' just means we go check if some other
  6318. * task can run, and if not we return here.
  6319. */
  6320. for(;;) pause();
  6321. }
  6322.  
  6323. static int printf(const char *fmt, ...)
  6324. {
  6325. va_list args;
  6326. int i;
  6327.  
  6328. va_start(args, fmt);
  6329. write(1,printbuf,i=vsprintf(printbuf, fmt, args));
  6330. va_end(args);
  6331. return i;
  6332. }
  6333.  
  6334. static char * argv[] = { "-",NULL };
  6335. static char * envp[] = { "HOME=/usr/root", NULL };
  6336.  
  6337. void init(void)
  6338. {
  6339. int i,j;
  6340.  
  6341. setup();
  6342. if (!fork())
  6343. _exit(execve("/bin/update",NULL,NULL));
  6344. (void) open("/dev/tty0",O_RDWR,0);
  6345. (void) dup(0);
  6346. (void) dup(0);
  6347. printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
  6348. NR_BUFFERS*BLOCK_SIZE);
  6349. printf(" Ok.\n\r");
  6350. if ((i=fork())<0)
  6351. printf("Fork failed in init\r\n");
  6352. else if (!i) {
  6353. close(0);close(1);close(2);
  6354. setsid();
  6355. (void) open("/dev/tty0",O_RDWR,0);
  6356. (void) dup(0);
  6357. (void) dup(0);
  6358. _exit(execve("/bin/sh",argv,envp));
  6359. }
  6360. j=wait(&i);
  6361. printf("child %d died with code %04x\n",j,i);
  6362. sync();
  6363. _exit(0); /* NOTE! _exit, not exit() */
  6364. }
  6365.  
  6366. ------------------------------------------------------------------------
  6367.  
  6368. kernel/asm.s
  6369.  
  6370. /*
  6371. * asm.s contains the low-level code for most hardware faults.
  6372. * page_exception is handled by the mm, so that isn't here. This
  6373. * file also handles (hopefully) fpu-exceptions due to TS-bit, as
  6374. * the fpu must be properly saved/resored. This hasn't been tested.
  6375. */
  6376.  
  6377. .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  6378. .globl _device_not_available,_double_fault,_coprocessor_segment_overrun
  6379. .globl _invalid_TSS,_segment_not_present,_stack_segment
  6380. .globl _general_protection,_coprocessor_error,_reserved
  6381.  
  6382. _divide_error:
  6383. pushl $_do_divide_error
  6384. no_error_code:
  6385. xchgl %eax,(%esp)
  6386. pushl %ebx
  6387. pushl %ecx
  6388. pushl %edx
  6389. pushl %edi
  6390. pushl %esi
  6391. pushl %ebp
  6392. push %ds
  6393. push %es
  6394. push %fs
  6395. pushl $0 # "error code"
  6396. lea 44(%esp),%edx
  6397. pushl %edx
  6398. movl $0x10,%edx
  6399. mov %dx,%ds
  6400. mov %dx,%es
  6401. mov %dx,%fs
  6402. call *%eax
  6403. addl $8,%esp
  6404. pop %fs
  6405. pop %es
  6406. pop %ds
  6407. popl %ebp
  6408. popl %esi
  6409. popl %edi
  6410. popl %edx
  6411. popl %ecx
  6412. popl %ebx
  6413. popl %eax
  6414. iret
  6415.  
  6416. _debug:
  6417. pushl $_do_int3 # _do_debug
  6418. jmp no_error_code
  6419.  
  6420. _nmi:
  6421. pushl $_do_nmi
  6422. jmp no_error_code
  6423.  
  6424. _int3:
  6425. pushl $_do_int3
  6426. jmp no_error_code
  6427.  
  6428. _overflow:
  6429. pushl $_do_overflow
  6430. jmp no_error_code
  6431.  
  6432. _bounds:
  6433. pushl $_do_bounds
  6434. jmp no_error_code
  6435.  
  6436. _invalid_op:
  6437. pushl $_do_invalid_op
  6438. jmp no_error_code
  6439.  
  6440. math_emulate:
  6441. popl %eax
  6442. pushl $_do_device_not_available
  6443. jmp no_error_code
  6444. _device_not_available:
  6445. pushl %eax
  6446. movl %cr0,%eax
  6447. bt $2,%eax # EM (math emulation bit)
  6448. jc math_emulate
  6449. clts # clear TS so that we can use math
  6450. movl _current,%eax
  6451. cmpl _last_task_used_math,%eax
  6452. je 1f # shouldn't happen really ...
  6453. pushl %ecx
  6454. pushl %edx
  6455. push %ds
  6456. movl $0x10,%eax
  6457. mov %ax,%ds
  6458. call _math_state_restore
  6459. pop %ds
  6460. popl %edx
  6461. popl %ecx
  6462. 1: popl %eax
  6463. iret
  6464.  
  6465. _coprocessor_segment_overrun:
  6466. pushl $_do_coprocessor_segment_overrun
  6467. jmp no_error_code
  6468.  
  6469. _reserved:
  6470. pushl $_do_reserved
  6471. jmp no_error_code
  6472.  
  6473. _coprocessor_error:
  6474. pushl $_do_coprocessor_error
  6475. jmp no_error_code
  6476.  
  6477. _double_fault:
  6478. pushl $_do_double_fault
  6479. error_code:
  6480. xchgl %eax,4(%esp) # error code <-> %eax
  6481. xchgl %ebx,(%esp) # &function <-> %ebx
  6482. pushl %ecx
  6483. pushl %edx
  6484. pushl %edi
  6485. pushl %esi
  6486. pushl %ebp
  6487. push %ds
  6488. push %es
  6489. push %fs
  6490. pushl %eax # error code
  6491. lea 44(%esp),%eax # offset
  6492. pushl %eax
  6493. movl $0x10,%eax
  6494. mov %ax,%ds
  6495. mov %ax,%es
  6496. mov %ax,%fs
  6497. call *%ebx
  6498. addl $8,%esp
  6499. pop %fs
  6500. pop %es
  6501. pop %ds
  6502. popl %ebp
  6503. popl %esi
  6504. popl %edi
  6505. popl %edx
  6506. popl %ecx
  6507. popl %ebx
  6508. popl %eax
  6509. iret
  6510.  
  6511. _invalid_TSS:
  6512. pushl $_do_invalid_TSS
  6513. jmp error_code
  6514.  
  6515. _segment_not_present:
  6516. pushl $_do_segment_not_present
  6517. jmp error_code
  6518.  
  6519. _stack_segment:
  6520. pushl $_do_stack_segment
  6521. jmp error_code
  6522.  
  6523. _general_protection:
  6524. pushl $_do_general_protection
  6525. jmp error_code
  6526.  
  6527.  
  6528. ------------------------------------------------------------------------
  6529.  
  6530. kernel/console.c
  6531.  
  6532. /*
  6533. * console.c
  6534. *
  6535. * This module implements the console io functions
  6536. * 'void con_init(void)'
  6537. * 'void con_write(struct tty_queue * queue)'
  6538. * Hopefully this will be a rather complete VT102 implementation.
  6539. *
  6540. */
  6541.  
  6542. /*
  6543. * NOTE!!! We sometimes disable and enable interrupts for a short while
  6544. * (to put a word in video IO), but this will work even for keyboard
  6545. * interrupts. We know interrupts aren't enabled when getting a keyboard
  6546. * interrupt, as we use trap-gates. Hopefully all is well.
  6547. */
  6548.  
  6549. #include <linux/sched.h>
  6550. #include <linux/tty.h>
  6551. #include <asm/io.h>
  6552. #include <asm/system.h>
  6553.  
  6554. #define SCREEN_START 0xb8000
  6555. #define SCREEN_END 0xc0000
  6556. #define LINES 25
  6557. #define COLUMNS 80
  6558. #define NPAR 16
  6559.  
  6560. extern void keyboard_interrupt(void);
  6561.  
  6562. static unsigned long origin=SCREEN_START;
  6563. static unsigned long scr_end=SCREEN_START+LINES*COLUMNS*2;
  6564. static unsigned long pos;
  6565. static unsigned long x,y;
  6566. static unsigned long top=0,bottom=LINES;
  6567. static unsigned long lines=LINES,columns=COLUMNS;
  6568. static unsigned long state=0;
  6569. static unsigned long npar,par[NPAR];
  6570. static unsigned long ques=0;
  6571. static unsigned char attr=0x07;
  6572.  
  6573. /*
  6574. * this is what the terminal answers to a ESC-Z or csi0c
  6575. * query (= vt100 response).
  6576. */
  6577. #define RESPONSE "\033[?1;2c"
  6578.  
  6579. static inline void gotoxy(unsigned int new_x,unsigned int new_y)
  6580. {
  6581. if (new_x>=columns || new_y>=lines)
  6582. return;
  6583. x=new_x;
  6584. y=new_y;
  6585. pos=origin+((y*columns+x)<<1);
  6586. }
  6587.  
  6588. static inline void set_origin(void)
  6589. {
  6590. cli();
  6591. outb_p(12,0x3d4);
  6592. outb_p(0xff&((origin-SCREEN_START)>>9),0x3d5);
  6593. outb_p(13,0x3d4);
  6594. outb_p(0xff&((origin-SCREEN_START)>>1),0x3d5);
  6595. sti();
  6596. }
  6597.  
  6598. static void scrup(void)
  6599. {
  6600. if (!top && bottom==lines) {
  6601. origin += columns<<1;
  6602. pos += columns<<1;
  6603. scr_end += columns<<1;
  6604. if (scr_end>SCREEN_END) {
  6605. __asm__("cld\n\t"
  6606. "rep\n\t"
  6607. "movsl\n\t"
  6608. "movl _columns,%1\n\t"
  6609. "rep\n\t"
  6610. "stosw"
  6611. ::"a" (0x0720),
  6612. "c" ((lines-1)*columns>>1),
  6613. "D" (SCREEN_START),
  6614. "S" (origin)
  6615. :"cx","di","si");
  6616. scr_end -= origin-SCREEN_START;
  6617. pos -= origin-SCREEN_START;
  6618. origin = SCREEN_START;
  6619. } else {
  6620. __asm__("cld\n\t"
  6621. "rep\n\t"
  6622. "stosl"
  6623. ::"a" (0x07200720),
  6624. "c" (columns>>1),
  6625. "D" (scr_end-(columns<<1))
  6626. :"cx","di");
  6627. }
  6628. set_origin();
  6629. } else {
  6630. __asm__("cld\n\t"
  6631. "rep\n\t"
  6632. "movsl\n\t"
  6633. "movl _columns,%%ecx\n\t"
  6634. "rep\n\t"
  6635. "stosw"
  6636. ::"a" (0x0720),
  6637. "c" ((bottom-top-1)*columns>>1),
  6638. "D" (origin+(columns<<1)*top),
  6639. "S" (origin+(columns<<1)*(top+1))
  6640. :"cx","di","si");
  6641. }
  6642. }
  6643.  
  6644. static void scrdown(void)
  6645. {
  6646. __asm__("std\n\t"
  6647. "rep\n\t"
  6648. "movsl\n\t"
  6649. "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */
  6650. "movl _columns,%%ecx\n\t"
  6651. "rep\n\t"
  6652. "stosw"
  6653. ::"a" (0x0720),
  6654. "c" ((bottom-top-1)*columns>>1),
  6655. "D" (origin+(columns<<1)*bottom-4),
  6656. "S" (origin+(columns<<1)*(bottom-1)-4)
  6657. :"ax","cx","di","si");
  6658. }
  6659.  
  6660. static void lf(void)
  6661. {
  6662. if (y+1<bottom) {
  6663. y++;
  6664. pos += columns<<1;
  6665. return;
  6666. }
  6667. scrup();
  6668. }
  6669.  
  6670. static void ri(void)
  6671. {
  6672. if (y>top) {
  6673. y--;
  6674. pos -= columns<<1;
  6675. return;
  6676. }
  6677. scrdown();
  6678. }
  6679.  
  6680. static void cr(void)
  6681. {
  6682. pos -= x<<1;
  6683. x=0;
  6684. }
  6685.  
  6686. static void del(void)
  6687. {
  6688. if (x) {
  6689. pos -= 2;
  6690. x--;
  6691. *(unsigned short *)pos = 0x0720;
  6692. }
  6693. }
  6694.  
  6695. static void csi_J(int par)
  6696. {
  6697. long count __asm__("cx");
  6698. long start __asm__("di");
  6699.  
  6700. switch (par) {
  6701. case 0: /* erase from cursor to end of display */
  6702. count = (scr_end-pos)>>1;
  6703. start = pos;
  6704. break;
  6705. case 1: /* erase from start to cursor */
  6706. count = (pos-origin)>>1;
  6707. start = origin;
  6708. break;
  6709. case 2: /* erase whole display */
  6710. count = columns*lines;
  6711. start = origin;
  6712. break;
  6713. default:
  6714. return;
  6715. }
  6716. __asm__("cld\n\t"
  6717. "rep\n\t"
  6718. "stosw\n\t"
  6719. ::"c" (count),
  6720. "D" (start),"a" (0x0720)
  6721. :"cx","di");
  6722. }
  6723.  
  6724. static void csi_K(int par)
  6725. {
  6726. long count __asm__("cx");
  6727. long start __asm__("di");
  6728.  
  6729. switch (par) {
  6730. case 0: /* erase from cursor to end of line */
  6731. if (x>=columns)
  6732. return;
  6733. count = columns-x;
  6734. start = pos;
  6735. break;
  6736. case 1: /* erase from start of line to cursor */
  6737. start = pos - (x<<1);
  6738. count = (x<columns)?x:columns;
  6739. break;
  6740. case 2: /* erase whole line */
  6741. start = pos - (x<<1);
  6742. count = columns;
  6743. break;
  6744. default:
  6745. return;
  6746. }
  6747. __asm__("cld\n\t"
  6748. "rep\n\t"
  6749. "stosw\n\t"
  6750. ::"c" (count),
  6751. "D" (start),"a" (0x0720)
  6752. :"cx","di");
  6753. }
  6754.  
  6755. void csi_m(void)
  6756. {
  6757. int i;
  6758.  
  6759. for (i=0;i<=npar;i++)
  6760. switch (par[i]) {
  6761. case 0:attr=0x07;break;
  6762. case 1:attr=0x0f;break;
  6763. case 4:attr=0x0f;break;
  6764. case 7:attr=0x70;break;
  6765. case 27:attr=0x07;break;
  6766. }
  6767. }
  6768.  
  6769. static inline void set_cursor(void)
  6770. {
  6771. cli();
  6772. outb_p(14,0x3d4);
  6773. outb_p(0xff&((pos-SCREEN_START)>>9),0x3d5);
  6774. outb_p(15,0x3d4);
  6775. outb_p(0xff&((pos-SCREEN_START)>>1),0x3d5);
  6776. sti();
  6777. }
  6778.  
  6779. static void respond(struct tty_struct * tty)
  6780. {
  6781. char * p = RESPONSE;
  6782.  
  6783. cli();
  6784. while (*p) {
  6785. PUTCH(*p,tty->read_q);
  6786. p++;
  6787. }
  6788. sti();
  6789. copy_to_cooked(tty);
  6790. }
  6791.  
  6792. static void insert_char(void)
  6793. {
  6794. int i=x;
  6795. unsigned short tmp,old=0x0720;
  6796. unsigned short * p = (unsigned short *) pos;
  6797.  
  6798. while (i++<columns) {
  6799. tmp=*p;
  6800. *p=old;
  6801. old=tmp;
  6802. p++;
  6803. }
  6804. }
  6805.  
  6806. static void insert_line(void)
  6807. {
  6808. int oldtop,oldbottom;
  6809.  
  6810. oldtop=top;
  6811. oldbottom=bottom;
  6812. top=y;
  6813. bottom=lines;
  6814. scrdown();
  6815. top=oldtop;
  6816. bottom=oldbottom;
  6817. }
  6818.  
  6819. static void delete_char(void)
  6820. {
  6821. int i;
  6822. unsigned short * p = (unsigned short *) pos;
  6823.  
  6824. if (x>=columns)
  6825. return;
  6826. i = x;
  6827. while (++i < columns) {
  6828. *p = *(p+1);
  6829. p++;
  6830. }
  6831. *p=0x0720;
  6832. }
  6833.  
  6834. static void delete_line(void)
  6835. {
  6836. int oldtop,oldbottom;
  6837.  
  6838. oldtop=top;
  6839. oldbottom=bottom;
  6840. top=y;
  6841. bottom=lines;
  6842. scrup();
  6843. top=oldtop;
  6844. bottom=oldbottom;
  6845. }
  6846.  
  6847. static void csi_at(int nr)
  6848. {
  6849. if (nr>columns)
  6850. nr=columns;
  6851. else if (!nr)
  6852. nr=1;
  6853. while (nr--)
  6854. insert_char();
  6855. }
  6856.  
  6857. static void csi_L(int nr)
  6858. {
  6859. if (nr>lines)
  6860. nr=lines;
  6861. else if (!nr)
  6862. nr=1;
  6863. while (nr--)
  6864. insert_line();
  6865. }
  6866.  
  6867. static void csi_P(int nr)
  6868. {
  6869. if (nr>columns)
  6870. nr=columns;
  6871. else if (!nr)
  6872. nr=1;
  6873. while (nr--)
  6874. delete_char();
  6875. }
  6876.  
  6877. static void csi_M(int nr)
  6878. {
  6879. if (nr>lines)
  6880. nr=lines;
  6881. else if (!nr)
  6882. nr=1;
  6883. while (nr--)
  6884. delete_line();
  6885. }
  6886.  
  6887. static int saved_x=0;
  6888. static int saved_y=0;
  6889.  
  6890. static void save_cur(void)
  6891. {
  6892. saved_x=x;
  6893. saved_y=y;
  6894. }
  6895.  
  6896. static void restore_cur(void)
  6897. {
  6898. x=saved_x;
  6899. y=saved_y;
  6900. pos=origin+((y*columns+x)<<1);
  6901. }
  6902.  
  6903. void con_write(struct tty_struct * tty)
  6904. {
  6905. int nr;
  6906. char c;
  6907.  
  6908. nr = CHARS(tty->write_q);
  6909. while (nr--) {
  6910. GETCH(tty->write_q,c);
  6911. switch(state) {
  6912. case 0:
  6913. if (c>31 && c<127) {
  6914. if (x>=columns) {
  6915. x -= columns;
  6916. pos -= columns<<1;
  6917. lf();
  6918. }
  6919. __asm__("movb _attr,%%ah\n\t"
  6920. "movw %%ax,%1\n\t"
  6921. ::"a" (c),"m" (*(short *)pos)
  6922. :"ax");
  6923. pos += 2;
  6924. x++;
  6925. } else if (c==27)
  6926. state=1;
  6927. else if (c==10 || c==11 || c==12)
  6928. lf();
  6929. else if (c==13)
  6930. cr();
  6931. else if (c==ERASE_CHAR(tty))
  6932. del();
  6933. else if (c==8) {
  6934. if (x) {
  6935. x--;
  6936. pos -= 2;
  6937. }
  6938. } else if (c==9) {
  6939. c=8-(x&7);
  6940. x += c;
  6941. pos += c<<1;
  6942. if (x>columns) {
  6943. x -= columns;
  6944. pos -= columns<<1;
  6945. lf();
  6946. }
  6947. c=9;
  6948. }
  6949. break;
  6950. case 1:
  6951. state=0;
  6952. if (c=='[')
  6953. state=2;
  6954. else if (c=='E')
  6955. gotoxy(0,y+1);
  6956. else if (c=='M')
  6957. ri();
  6958. else if (c=='D')
  6959. lf();
  6960. else if (c=='Z')
  6961. respond(tty);
  6962. else if (x=='7')
  6963. save_cur();
  6964. else if (x=='8')
  6965. restore_cur();
  6966. break;
  6967. case 2:
  6968. for(npar=0;npar<NPAR;npar++)
  6969. par[npar]=0;
  6970. npar=0;
  6971. state=3;
  6972. if (ques=(c=='?'))
  6973. break;
  6974. case 3:
  6975. if (c==';' && npar<NPAR-1) {
  6976. npar++;
  6977. break;
  6978. } else if (c>='0' && c<='9') {
  6979. par[npar]=10*par[npar]+c-'0';
  6980. break;
  6981. } else state=4;
  6982. case 4:
  6983. state=0;
  6984. switch(c) {
  6985. case 'G': case '`':
  6986. if (par[0]) par[0]--;
  6987. gotoxy(par[0],y);
  6988. break;
  6989. case 'A':
  6990. if (!par[0]) par[0]++;
  6991. gotoxy(x,y-par[0]);
  6992. break;
  6993. case 'B': case 'e':
  6994. if (!par[0]) par[0]++;
  6995. gotoxy(x,y+par[0]);
  6996. break;
  6997. case 'C': case 'a':
  6998. if (!par[0]) par[0]++;
  6999. gotoxy(x+par[0],y);
  7000. break;
  7001. case 'D':
  7002. if (!par[0]) par[0]++;
  7003. gotoxy(x-par[0],y);
  7004. break;
  7005. case 'E':
  7006. if (!par[0]) par[0]++;
  7007. gotoxy(0,y+par[0]);
  7008. break;
  7009. case 'F':
  7010. if (!par[0]) par[0]++;
  7011. gotoxy(0,y-par[0]);
  7012. break;
  7013. case 'd':
  7014. if (par[0]) par[0]--;
  7015. gotoxy(x,par[0]);
  7016. break;
  7017. case 'H': case 'f':
  7018. if (par[0]) par[0]--;
  7019. if (par[1]) par[1]--;
  7020. gotoxy(par[1],par[0]);
  7021. break;
  7022. case 'J':
  7023. csi_J(par[0]);
  7024. break;
  7025. case 'K':
  7026. csi_K(par[0]);
  7027. break;
  7028. case 'L':
  7029. csi_L(par[0]);
  7030. break;
  7031. case 'M':
  7032. csi_M(par[0]);
  7033. break;
  7034. case 'P':
  7035. csi_P(par[0]);
  7036. break;
  7037. case '@':
  7038. csi_at(par[0]);
  7039. break;
  7040. case 'm':
  7041. csi_m();
  7042. break;
  7043. case 'r':
  7044. if (par[0]) par[0]--;
  7045. if (!par[1]) par[1]=lines;
  7046. if (par[0] < par[1] &&
  7047. par[1] <= lines) {
  7048. top=par[0];
  7049. bottom=par[1];
  7050. }
  7051. break;
  7052. case 's':
  7053. save_cur();
  7054. break;
  7055. case 'u':
  7056. restore_cur();
  7057. break;
  7058. }
  7059. }
  7060. }
  7061. set_cursor();
  7062. }
  7063.  
  7064. /*
  7065. * void con_init(void);
  7066. *
  7067. * This routine initalizes console interrupts, and does nothing
  7068. * else. If you want the screen to clear, call tty_write with
  7069. * the appropriate escape-sequece.
  7070. */
  7071. void con_init(void)
  7072. {
  7073. register unsigned char a;
  7074.  
  7075. gotoxy(*(unsigned char *)(0x90000+510),*(unsigned char *)(0x90000+511));
  7076. set_trap_gate(0x21,&keyboard_interrupt);
  7077. outb_p(inb_p(0x21)&0xfd,0x21);
  7078. a=inb_p(0x61);
  7079. outb_p(a|0x80,0x61);
  7080. outb(a,0x61);
  7081. }
  7082.  
  7083. ------------------------------------------------------------------------
  7084.  
  7085. kernel/exit.c
  7086.  
  7087. #include <errno.h>
  7088. #include <signal.h>
  7089. #include <sys/wait.h>
  7090.  
  7091. #include <linux/sched.h>
  7092. #include <linux/kernel.h>
  7093. #include <linux/tty.h>
  7094. #include <asm/segment.h>
  7095.  
  7096. int sys_pause(void);
  7097. int sys_close(int fd);
  7098.  
  7099. void release(struct task_struct * p)
  7100. {
  7101. int i;
  7102.  
  7103. if (!p)
  7104. return;
  7105. for (i=1 ; i<NR_TASKS ; i++)
  7106. if (task[i]==p) {
  7107. task[i]=NULL;
  7108. free_page((long)p);
  7109. schedule();
  7110. return;
  7111. }
  7112. panic("trying to release non-existent task");
  7113. }
  7114.  
  7115. static inline void send_sig(long sig,struct task_struct * p,int priv)
  7116. {
  7117. if (!p || sig<1 || sig>32)
  7118. return;
  7119. if (priv ||
  7120. current->uid==p->uid ||
  7121. current->euid==p->uid ||
  7122. current->uid==p->euid ||
  7123. current->euid==p->euid)
  7124. p->signal |= (1<<(sig-1));
  7125. }
  7126.  
  7127. void do_kill(long pid,long sig,int priv)
  7128. {
  7129. struct task_struct **p = NR_TASKS + task;
  7130.  
  7131. if (!pid) while (--p > &FIRST_TASK) {
  7132. if (*p && (*p)->pgrp == current->pid)
  7133. send_sig(sig,*p,priv);
  7134. } else if (pid>0) while (--p > &FIRST_TASK) {
  7135. if (*p && (*p)->pid == pid)
  7136. send_sig(sig,*p,priv);
  7137. } else if (pid == -1) while (--p > &FIRST_TASK)
  7138. send_sig(sig,*p,priv);
  7139. else while (--p > &FIRST_TASK)
  7140. if (*p && (*p)->pgrp == -pid)
  7141. send_sig(sig,*p,priv);
  7142. }
  7143.  
  7144. int sys_kill(int pid,int sig)
  7145. {
  7146. do_kill(pid,sig,!(current->uid || current->euid));
  7147. return 0;
  7148. }
  7149.  
  7150. int do_exit(long code)
  7151. {
  7152. int i;
  7153.  
  7154. free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
  7155. free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
  7156. for (i=0 ; i<NR_TASKS ; i++)
  7157. if (task[i] && task[i]->father == current->pid)
  7158. task[i]->father = 0;
  7159. for (i=0 ; i<NR_OPEN ; i++)
  7160. if (current->filp[i])
  7161. sys_close(i);
  7162. iput(current->pwd);
  7163. current->pwd=NULL;
  7164. iput(current->root);
  7165. current->root=NULL;
  7166. if (current->leader && current->tty >= 0)
  7167. tty_table[current->tty].pgrp = 0;
  7168. if (last_task_used_math == current)
  7169. last_task_used_math = NULL;
  7170. if (current->father) {
  7171. current->state = TASK_ZOMBIE;
  7172. do_kill(current->father,SIGCHLD,1);
  7173. current->exit_code = code;
  7174. } else
  7175. release(current);
  7176. schedule();
  7177. return (-1); /* just to suppress warnings */
  7178. }
  7179.  
  7180. int sys_exit(int error_code)
  7181. {
  7182. return do_exit((error_code&0xff)<<8);
  7183. }
  7184.  
  7185. int sys_waitpid(pid_t pid,int * stat_addr, int options)
  7186. {
  7187. int flag=0;
  7188. struct task_struct ** p;
  7189.  
  7190. verify_area(stat_addr,4);
  7191. repeat:
  7192. for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
  7193. if (*p && *p != current &&
  7194. (pid==-1 || (*p)->pid==pid ||
  7195. (pid==0 && (*p)->pgrp==current->pgrp) ||
  7196. (pid<0 && (*p)->pgrp==-pid)))
  7197. if ((*p)->father == current->pid) {
  7198. flag=1;
  7199. if ((*p)->state==TASK_ZOMBIE) {
  7200. put_fs_long((*p)->exit_code,
  7201. (unsigned long *) stat_addr);
  7202. current->cutime += (*p)->utime;
  7203. current->cstime += (*p)->stime;
  7204. flag = (*p)->pid;
  7205. release(*p);
  7206. return flag;
  7207. }
  7208. }
  7209. if (flag) {
  7210. if (options & WNOHANG)
  7211. return 0;
  7212. sys_pause();
  7213. if (!(current->signal &= ~(1<<(SIGCHLD-1))))
  7214. goto repeat;
  7215. else
  7216. return -EINTR;
  7217. }
  7218. return -ECHILD;
  7219. }
  7220.  
  7221.  
  7222.  
  7223. ------------------------------------------------------------------------
  7224.  
  7225. kernel/fork.c
  7226.  
  7227. /*
  7228. * 'fork.c' contains the help-routines for the 'fork' system call
  7229. * (see also system_call.s), and some misc functions ('verify_area').
  7230. * Fork is rather simple, once you get the hang of it, but the memory
  7231. * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
  7232. */
  7233. #include <errno.h>
  7234.  
  7235. #include <linux/sched.h>
  7236. #include <linux/kernel.h>
  7237. #include <asm/segment.h>
  7238. #include <asm/system.h>
  7239.  
  7240. extern void write_verify(unsigned long address);
  7241.  
  7242. long last_pid=0;
  7243.  
  7244. void verify_area(void * addr,int size)
  7245. {
  7246. unsigned long start;
  7247.  
  7248. start = (unsigned long) addr;
  7249. size += start & 0xfff;
  7250. start &= 0xfffff000;
  7251. start += get_base(current->ldt[2]);
  7252. while (size>0) {
  7253. size -= 4096;
  7254. write_verify(start);
  7255. start += 4096;
  7256. }
  7257. }
  7258.  
  7259. int copy_mem(int nr,struct task_struct * p)
  7260. {
  7261. unsigned long old_data_base,new_data_base,data_limit;
  7262. unsigned long old_code_base,new_code_base,code_limit;
  7263.  
  7264. code_limit=get_limit(0x0f);
  7265. data_limit=get_limit(0x17);
  7266. old_code_base = get_base(current->ldt[1]);
  7267. old_data_base = get_base(current->ldt[2]);
  7268. if (old_data_base != old_code_base)
  7269. panic("We don't support separate I&D");
  7270. if (data_limit < code_limit)
  7271. panic("Bad data_limit");
  7272. new_data_base = new_code_base = nr * 0x4000000;
  7273. set_base(p->ldt[1],new_code_base);
  7274. set_base(p->ldt[2],new_data_base);
  7275. if (copy_page_tables(old_data_base,new_data_base,data_limit)) {
  7276. free_page_tables(new_data_base,data_limit);
  7277. return -ENOMEM;
  7278. }
  7279. return 0;
  7280. }
  7281.  
  7282. /*
  7283. * Ok, this is the main fork-routine. It copies the system process
  7284. * information (task[nr]) and sets up the necessary registers. It
  7285. * also copies the data segment in it's entirety.
  7286. */
  7287. int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
  7288. long ebx,long ecx,long edx,
  7289. long fs,long es,long ds,
  7290. long eip,long cs,long eflags,long esp,long ss)
  7291. {
  7292. struct task_struct *p;
  7293. int i;
  7294. struct file *f;
  7295.  
  7296. p = (struct task_struct *) get_free_page();
  7297. if (!p)
  7298. return -EAGAIN;
  7299. *p = *current; /* NOTE! this doesn't copy the supervisor stack */
  7300. p->state = TASK_RUNNING;
  7301. p->pid = last_pid;
  7302. p->father = current->pid;
  7303. p->counter = p->priority;
  7304. p->signal = 0;
  7305. p->alarm = 0;
  7306. p->leader = 0; /* process leadership doesn't inherit */
  7307. p->utime = p->stime = 0;
  7308. p->cutime = p->cstime = 0;
  7309. p->start_time = jiffies;
  7310. p->tss.back_link = 0;
  7311. p->tss.esp0 = PAGE_SIZE + (long) p;
  7312. p->tss.ss0 = 0x10;
  7313. p->tss.eip = eip;
  7314. p->tss.eflags = eflags;
  7315. p->tss.eax = 0;
  7316. p->tss.ecx = ecx;
  7317. p->tss.edx = edx;
  7318. p->tss.ebx = ebx;
  7319. p->tss.esp = esp;
  7320. p->tss.ebp = ebp;
  7321. p->tss.esi = esi;
  7322. p->tss.edi = edi;
  7323. p->tss.es = es & 0xffff;
  7324. p->tss.cs = cs & 0xffff;
  7325. p->tss.ss = ss & 0xffff;
  7326. p->tss.ds = ds & 0xffff;
  7327. p->tss.fs = fs & 0xffff;
  7328. p->tss.gs = gs & 0xffff;
  7329. p->tss.ldt = _LDT(nr);
  7330. p->tss.trace_bitmap = 0x80000000;
  7331. if (last_task_used_math == current)
  7332. __asm__("fnsave %0"::"m" (p->tss.i387));
  7333. if (copy_mem(nr,p)) {
  7334. free_page((long) p);
  7335. return -EAGAIN;
  7336. }
  7337. for (i=0; i<NR_OPEN;i++)
  7338. if (f=p->filp[i])
  7339. f->f_count++;
  7340. if (current->pwd)
  7341. current->pwd->i_count++;
  7342. if (current->root)
  7343. current->root->i_count++;
  7344. set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
  7345. set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
  7346. task[nr] = p; /* do this last, just in case */
  7347. return last_pid;
  7348. }
  7349.  
  7350. int find_empty_process(void)
  7351. {
  7352. int i;
  7353.  
  7354. repeat:
  7355. if ((++last_pid)<0) last_pid=1;
  7356. for(i=0 ; i<NR_TASKS ; i++)
  7357. if (task[i] && task[i]->pid == last_pid) goto repeat;
  7358. for(i=1 ; i<NR_TASKS ; i++)
  7359. if (!task[i])
  7360. return i;
  7361. return -EAGAIN;
  7362. }
  7363.  
  7364. ------------------------------------------------------------------------
  7365.  
  7366. kernel/hd.c
  7367.  
  7368. #include <linux/config.h>
  7369. #include <linux/sched.h>
  7370. #include <linux/fs.h>
  7371. #include <linux/kernel.h>
  7372. #include <linux/hdreg.h>
  7373. #include <asm/system.h>
  7374. #include <asm/io.h>
  7375. #include <asm/segment.h>
  7376.  
  7377. /*
  7378. * This code handles all hd-interrupts, and read/write requests to
  7379. * the hard-disk. It is relatively straigthforward (not obvious maybe,
  7380. * but interrupts never are), while still being efficient, and never
  7381. * disabling interrupts (except to overcome possible race-condition).
  7382. * The elevator block-seek algorithm doesn't need to disable interrupts
  7383. * due to clever programming.
  7384. */
  7385.  
  7386. /* Max read/write errors/sector */
  7387. #define MAX_ERRORS 5
  7388. #define MAX_HD 2
  7389. #define NR_REQUEST 32
  7390.  
  7391. /*
  7392. * This struct defines the HD's and their types.
  7393. * Currently defined for CP3044's, ie a modified
  7394. * type 17.
  7395. */
  7396. static struct hd_i_struct{
  7397. int head,sect,cyl,wpcom,lzone,ctl;
  7398. } hd_info[]= { HD_TYPE };
  7399.  
  7400. #define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct)))
  7401.  
  7402. static struct hd_struct {
  7403. long start_sect;
  7404. long nr_sects;
  7405. } hd[5*MAX_HD]={{0,0},};
  7406.  
  7407. static struct hd_request {
  7408. int hd; /* -1 if no request */
  7409. int nsector;
  7410. int sector;
  7411. int head;
  7412. int cyl;
  7413. int cmd;
  7414. int errors;
  7415. struct buffer_head * bh;
  7416. struct hd_request * next;
  7417. } request[NR_REQUEST];
  7418.  
  7419. #define IN_ORDER(s1,s2) \
  7420. ((s1)->hd<(s2)->hd || (s1)->hd==(s2)->hd && \
  7421. ((s1)->cyl<(s2)->cyl || (s1)->cyl==(s2)->cyl && \
  7422. ((s1)->head<(s2)->head || (s1)->head==(s2)->head && \
  7423. ((s1)->sector<(s2)->sector))))
  7424.  
  7425. static struct hd_request * this_request = NULL;
  7426.  
  7427. static int sorting=0;
  7428.  
  7429. static void do_request(void);
  7430. static void reset_controller(void);
  7431. static void rw_abs_hd(int rw,unsigned int nr,unsigned int sec,unsigned int head,
  7432. unsigned int cyl,struct buffer_head * bh);
  7433. void hd_init(void);
  7434.  
  7435. #define port_read(port,buf,nr) \
  7436. __asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di")
  7437.  
  7438. #define port_write(port,buf,nr) \
  7439. __asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")
  7440.  
  7441. extern void hd_interrupt(void);
  7442.  
  7443. static struct task_struct * wait_for_request=NULL;
  7444.  
  7445. static inline void lock_buffer(struct buffer_head * bh)
  7446. {
  7447. if (bh->b_lock)
  7448. printk("hd.c: buffer multiply locked\n");
  7449. bh->b_lock=1;
  7450. }
  7451.  
  7452. static inline void unlock_buffer(struct buffer_head * bh)
  7453. {
  7454. if (!bh->b_lock)
  7455. printk("hd.c: free buffer being unlocked\n");
  7456. bh->b_lock=0;
  7457. wake_up(&bh->b_wait);
  7458. }
  7459.  
  7460. static inline void wait_on_buffer(struct buffer_head * bh)
  7461. {
  7462. cli();
  7463. while (bh->b_lock)
  7464. sleep_on(&bh->b_wait);
  7465. sti();
  7466. }
  7467.  
  7468. void rw_hd(int rw, struct buffer_head * bh)
  7469. {
  7470. unsigned int block,dev;
  7471. unsigned int sec,head,cyl;
  7472.  
  7473. block = bh->b_blocknr << 1;
  7474. dev = MINOR(bh->b_dev);
  7475. if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects)
  7476. return;
  7477. block += hd[dev].start_sect;
  7478. dev /= 5;
  7479. __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),
  7480. "r" (hd_info[dev].sect));
  7481. __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
  7482. "r" (hd_info[dev].head));
  7483. rw_abs_hd(rw,dev,sec+1,head,cyl,bh);
  7484. }
  7485.  
  7486. /* This may be used only once, enforced by 'static int callable' */
  7487. int sys_setup(void)
  7488. {
  7489. static int callable = 1;
  7490. int i,drive;
  7491. struct partition *p;
  7492.  
  7493. if (!callable)
  7494. return -1;
  7495. callable = 0;
  7496. for (drive=0 ; drive<NR_HD ; drive++) {
  7497. rw_abs_hd(READ,drive,1,0,0,(struct buffer_head *) start_buffer);
  7498. if (!start_buffer->b_uptodate) {
  7499. printk("Unable to read partition table of drive %d\n\r",
  7500. drive);
  7501. panic("");
  7502. }
  7503. if (start_buffer->b_data[510] != 0x55 || (unsigned char)
  7504. start_buffer->b_data[511] != 0xAA) {
  7505. printk("Bad partition table on drive %d\n\r",drive);
  7506. panic("");
  7507. }
  7508. p = 0x1BE + (void *)start_buffer->b_data;
  7509. for (i=1;i<5;i++,p++) {
  7510. hd[i+5*drive].start_sect = p->start_sect;
  7511. hd[i+5*drive].nr_sects = p->nr_sects;
  7512. }
  7513. }
  7514. printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
  7515. mount_root();
  7516. return (0);
  7517. }
  7518.  
  7519. /*
  7520. * This is the pointer to a routine to be executed at every hd-interrupt.
  7521. * Interesting way of doing things, but should be rather practical.
  7522. */
  7523. void (*do_hd)(void) = NULL;
  7524.  
  7525. static int controller_ready(void)
  7526. {
  7527. int retries=1000;
  7528.  
  7529. while (--retries && (inb(HD_STATUS)&0xc0)!=0x40);
  7530. return (retries);
  7531. }
  7532.  
  7533. static int win_result(void)
  7534. {
  7535. int i=inb(HD_STATUS);
  7536.  
  7537. if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
  7538. == (READY_STAT | SEEK_STAT))
  7539. return(0); /* ok */
  7540. if (i&1) i=inb(HD_ERROR);
  7541. return (1);
  7542. }
  7543.  
  7544. static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
  7545. unsigned int head,unsigned int cyl,unsigned int cmd,
  7546. void (*intr_addr)(void))
  7547. {
  7548. register int port asm("dx");
  7549.  
  7550. if (drive>1 || head>15)
  7551. panic("Trying to write bad sector");
  7552. if (!controller_ready())
  7553. panic("HD controller not ready");
  7554. do_hd = intr_addr;
  7555. outb(_CTL,HD_CMD);
  7556. port=HD_DATA;
  7557. outb_p(_WPCOM,++port);
  7558. outb_p(nsect,++port);
  7559. outb_p(sect,++port);
  7560. outb_p(cyl,++port);
  7561. outb_p(cyl>>8,++port);
  7562. outb_p(0xA0|(drive<<4)|head,++port);
  7563. outb(cmd,++port);
  7564. }
  7565.  
  7566. static int drive_busy(void)
  7567. {
  7568. unsigned int i;
  7569.  
  7570. for (i = 0; i < 100000; i++)
  7571. if (READY_STAT == (inb(HD_STATUS) & (BUSY_STAT | READY_STAT)))
  7572. break;
  7573. i = inb(HD_STATUS);
  7574. i &= BUSY_STAT | READY_STAT | SEEK_STAT;
  7575. if (i == READY_STAT | SEEK_STAT)
  7576. return(0);
  7577. printk("HD controller times out\n\r");
  7578. return(1);
  7579. }
  7580.  
  7581. static void reset_controller(void)
  7582. {
  7583. int i;
  7584.  
  7585. outb(4,HD_CMD);
  7586. for(i = 0; i < 1000; i++) nop();
  7587. outb(0,HD_CMD);
  7588. for(i = 0; i < 10000 && drive_busy(); i++) /* nothing */;
  7589. if (drive_busy())
  7590. printk("HD-controller still busy\n\r");
  7591. if((i = inb(ERR_STAT)) != 1)
  7592. printk("HD-controller reset failed: %02x\n\r",i);
  7593. }
  7594.  
  7595. static void reset_hd(int nr)
  7596. {
  7597. reset_controller();
  7598. hd_out(nr,_SECT,_SECT,_HEAD-1,_CYL,WIN_SPECIFY,&do_request);
  7599. }
  7600.  
  7601. void unexpected_hd_interrupt(void)
  7602. {
  7603. panic("Unexpected HD interrupt\n\r");
  7604. }
  7605.  
  7606. static void bad_rw_intr(void)
  7607. {
  7608. int i = this_request->hd;
  7609.  
  7610. if (this_request->errors++ >= MAX_ERRORS) {
  7611. this_request->bh->b_uptodate = 0;
  7612. unlock_buffer(this_request->bh);
  7613. wake_up(&wait_for_request);
  7614. this_request->hd = -1;
  7615. this_request=this_request->next;
  7616. }
  7617. reset_hd(i);
  7618. }
  7619.  
  7620. static void read_intr(void)
  7621. {
  7622. if (win_result()) {
  7623. bad_rw_intr();
  7624. return;
  7625. }
  7626. port_read(HD_DATA,this_request->bh->b_data+
  7627. 512*(this_request->nsector&1),256);
  7628. this_request->errors = 0;
  7629. if (--this_request->nsector)
  7630. return;
  7631. this_request->bh->b_uptodate = 1;
  7632. this_request->bh->b_dirt = 0;
  7633. wake_up(&wait_for_request);
  7634. unlock_buffer(this_request->bh);
  7635. this_request->hd = -1;
  7636. this_request=this_request->next;
  7637. do_request();
  7638. }
  7639.  
  7640. static void write_intr(void)
  7641. {
  7642. if (win_result()) {
  7643. bad_rw_intr();
  7644. return;
  7645. }
  7646. if (--this_request->nsector) {
  7647. port_write(HD_DATA,this_request->bh->b_data+512,256);
  7648. return;
  7649. }
  7650. this_request->bh->b_uptodate = 1;
  7651. this_request->bh->b_dirt = 0;
  7652. wake_up(&wait_for_request);
  7653. unlock_buffer(this_request->bh);
  7654. this_request->hd = -1;
  7655. this_request=this_request->next;
  7656. do_request();
  7657. }
  7658.  
  7659. static void do_request(void)
  7660. {
  7661. int i,r;
  7662.  
  7663. if (sorting)
  7664. return;
  7665. if (!this_request) {
  7666. do_hd=NULL;
  7667. return;
  7668. }
  7669. if (this_request->cmd == WIN_WRITE) {
  7670. hd_out(this_request->hd,this_request->nsector,this_request->
  7671. sector,this_request->head,this_request->cyl,
  7672. this_request->cmd,&write_intr);
  7673. for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
  7674. /* nothing */ ;
  7675. if (!r) {
  7676. reset_hd(this_request->hd);
  7677. return;
  7678. }
  7679. port_write(HD_DATA,this_request->bh->b_data+
  7680. 512*(this_request->nsector&1),256);
  7681. } else if (this_request->cmd == WIN_READ) {
  7682. hd_out(this_request->hd,this_request->nsector,this_request->
  7683. sector,this_request->head,this_request->cyl,
  7684. this_request->cmd,&read_intr);
  7685. } else
  7686. panic("unknown hd-command");
  7687. }
  7688.  
  7689. /*
  7690. * add-request adds a request to the linked list.
  7691. * It sets the 'sorting'-variable when doing something
  7692. * that interrupts shouldn't touch.
  7693. */
  7694. static void add_request(struct hd_request * req)
  7695. {
  7696. struct hd_request * tmp;
  7697.  
  7698. if (req->nsector != 2)
  7699. panic("nsector!=2 not implemented");
  7700. /*
  7701. * Not to mess up the linked lists, we never touch the two first
  7702. * entries (not this_request, as it is used by current interrups,
  7703. * and not this_request->next, as it can be assigned to this_request).
  7704. * This is not too high a price to pay for the ability of not
  7705. * disabling interrupts.
  7706. */
  7707. sorting=1;
  7708. if (!(tmp=this_request))
  7709. this_request=req;
  7710. else {
  7711. if (!(tmp->next))
  7712. tmp->next=req;
  7713. else {
  7714. tmp=tmp->next;
  7715. for ( ; tmp->next ; tmp=tmp->next)
  7716. if ((IN_ORDER(tmp,req) ||
  7717. !IN_ORDER(tmp,tmp->next)) &&
  7718. IN_ORDER(req,tmp->next))
  7719. break;
  7720. req->next=tmp->next;
  7721. tmp->next=req;
  7722. }
  7723. }
  7724. sorting=0;
  7725. /*
  7726. * NOTE! As a result of sorting, the interrupts may have died down,
  7727. * as they aren't redone due to locking with sorting=1. They might
  7728. * also never have started, if this is the first request in the queue,
  7729. * so we restart them if necessary.
  7730. */
  7731. if (!do_hd)
  7732. do_request();
  7733. }
  7734.  
  7735. void rw_abs_hd(int rw,unsigned int nr,unsigned int sec,unsigned int head,
  7736. unsigned int cyl,struct buffer_head * bh)
  7737. {
  7738. struct hd_request * req;
  7739.  
  7740. if (rw!=READ && rw!=WRITE)
  7741. panic("Bad hd command, must be R/W");
  7742. lock_buffer(bh);
  7743. repeat:
  7744. for (req=0+request ; req<NR_REQUEST+request ; req++)
  7745. if (req->hd<0)
  7746. break;
  7747. if (req==NR_REQUEST+request) {
  7748. sleep_on(&wait_for_request);
  7749. goto repeat;
  7750. }
  7751. req->hd=nr;
  7752. req->nsector=2;
  7753. req->sector=sec;
  7754. req->head=head;
  7755. req->cyl=cyl;
  7756. req->cmd = ((rw==READ)?WIN_READ:WIN_WRITE);
  7757. req->bh=bh;
  7758. req->errors=0;
  7759. req->next=NULL;
  7760. add_request(req);
  7761. wait_on_buffer(bh);
  7762. }
  7763.  
  7764. void hd_init(void)
  7765. {
  7766. int i;
  7767.  
  7768. for (i=0 ; i<NR_REQUEST ; i++) {
  7769. request[i].hd = -1;
  7770. request[i].next = NULL;
  7771. }
  7772. for (i=0 ; i<NR_HD ; i++) {
  7773. hd[i*5].start_sect = 0;
  7774. hd[i*5].nr_sects = hd_info[i].head*
  7775. hd_info[i].sect*hd_info[i].cyl;
  7776. }
  7777. set_trap_gate(0x2E,&hd_interrupt);
  7778. outb_p(inb_p(0x21)&0xfb,0x21);
  7779. outb(inb_p(0xA1)&0xbf,0xA1);
  7780. }
  7781.  
  7782. ------------------------------------------------------------------------
  7783.  
  7784. kernel/keyboard.s
  7785.  
  7786. /*
  7787. * keyboard.s
  7788. */
  7789.  
  7790. .text
  7791. .globl _keyboard_interrupt
  7792.  
  7793. /*
  7794. * these are for the keyboard read functions
  7795. */
  7796. size = 1024 /* must be a power of two ! And MUST be the same
  7797. as in tty_io.c !!!! */
  7798. head = 4
  7799. tail = 8
  7800. proc_list = 12
  7801. buf = 16
  7802.  
  7803. mode: .byte 0 /* caps, alt, ctrl and shift mode */
  7804. leds: .byte 2 /* num-lock, caps, scroll-lock mode (nom-lock on) */
  7805. e0: .byte 0
  7806.  
  7807. /*
  7808. * con_int is the real interrupt routine that reads the
  7809. * keyboard scan-code and converts it into the appropriate
  7810. * ascii character(s).
  7811. */
  7812. _keyboard_interrupt:
  7813. pushl %eax
  7814. pushl %ebx
  7815. pushl %ecx
  7816. pushl %edx
  7817. push %ds
  7818. push %es
  7819. movl $0x10,%eax
  7820. mov %ax,%ds
  7821. mov %ax,%es
  7822. xorl %al,%al /* %eax is scan code */
  7823. inb $0x60,%al
  7824. cmpb $0xe0,%al
  7825. je set_e0
  7826. cmpb $0xe1,%al
  7827. je set_e1
  7828. call key_table(,%eax,4)
  7829. movb $0,e0
  7830. e0_e1: inb $0x61,%al
  7831. jmp 1f
  7832. 1: jmp 1f
  7833. 1: orb $0x80,%al
  7834. jmp 1f
  7835. 1: jmp 1f
  7836. 1: outb %al,$0x61
  7837. jmp 1f
  7838. 1: jmp 1f
  7839. 1: andb $0x7F,%al
  7840. outb %al,$0x61
  7841. movb $0x20,%al
  7842. outb %al,$0x20
  7843. pushl $0
  7844. call _do_tty_interrupt
  7845. addl $4,%esp
  7846. pop %es
  7847. pop %ds
  7848. popl %edx
  7849. popl %ecx
  7850. popl %ebx
  7851. popl %eax
  7852. iret
  7853. set_e0: movb $1,e0
  7854. jmp e0_e1
  7855. set_e1: movb $2,e0
  7856. jmp e0_e1
  7857.  
  7858. /*
  7859. * This routine fills the buffer with max 8 bytes, taken from
  7860. * %ebx:%eax. (%edx is high). The bytes are written in the
  7861. * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
  7862. */
  7863. put_queue:
  7864. pushl %ecx
  7865. pushl %edx
  7866. movl _table_list,%edx # read-queue for console
  7867. movl head(%edx),%ecx
  7868. 1: movb %al,buf(%edx,%ecx)
  7869. incl %ecx
  7870. andl $size-1,%ecx
  7871. cmpl tail(%edx),%ecx # buffer full - discard everything
  7872. je 3f
  7873. shrdl $8,%ebx,%eax
  7874. je 2f
  7875. shrl $8,%ebx
  7876. jmp 1b
  7877. 2: movl %ecx,head(%edx)
  7878. movl proc_list(%edx),%ecx
  7879. testl %ecx,%ecx
  7880. je 3f
  7881. movl $0,(%ecx)
  7882. 3: popl %edx
  7883. popl %ecx
  7884. ret
  7885.  
  7886. ctrl: movb $0x04,%al
  7887. jmp 1f
  7888. alt: movb $0x10,%al
  7889. 1: cmpb $0,e0
  7890. je 2f
  7891. addb %al,%al
  7892. 2: orb %al,mode
  7893. ret
  7894. unctrl: movb $0x04,%al
  7895. jmp 1f
  7896. unalt: movb $0x10,%al
  7897. 1: cmpb $0,e0
  7898. je 2f
  7899. addb %al,%al
  7900. 2: notb %al
  7901. andb %al,mode
  7902. ret
  7903.  
  7904. lshift:
  7905. orb $0x01,mode
  7906. ret
  7907. unlshift:
  7908. andb $0xfe,mode
  7909. ret
  7910. rshift:
  7911. orb $0x02,mode
  7912. ret
  7913. unrshift:
  7914. andb $0xfd,mode
  7915. ret
  7916.  
  7917. caps: testb $0x80,mode
  7918. jne 1f
  7919. xorb $4,leds
  7920. xorb $0x40,mode
  7921. orb $0x80,mode
  7922. set_leds:
  7923. call kb_wait
  7924. movb $0xed,%al /* set leds command */
  7925. outb %al,$0x60
  7926. call kb_wait
  7927. movb leds,%al
  7928. outb %al,$0x60
  7929. ret
  7930. uncaps: andb $0x7f,mode
  7931. ret
  7932. scroll:
  7933. xorb $1,leds
  7934. jmp set_leds
  7935. num: xorb $2,leds
  7936. jmp set_leds
  7937.  
  7938. /*
  7939. * curosr-key/numeric keypad cursor keys are handled here.
  7940. * checking for numeric keypad etc.
  7941. */
  7942. cursor:
  7943. subb $0x47,%al
  7944. jb 1f
  7945. cmpb $12,%al
  7946. ja 1f
  7947. jne cur2 /* check for ctrl-alt-del */
  7948. testb $0x0c,mode
  7949. je cur2
  7950. testb $0x30,mode
  7951. jne reboot
  7952. cur2: cmpb $0x01,e0 /* e0 forces cursor movement */
  7953. je cur
  7954. testb $0x02,leds /* not num-lock forces cursor */
  7955. je cur
  7956. testb $0x03,mode /* shift forces cursor */
  7957. jne cur
  7958. xorl %ebx,%ebx
  7959. movb num_table(%eax),%al
  7960. jmp put_queue
  7961. 1: ret
  7962.  
  7963. cur: movb cur_table(%eax),%al
  7964. cmpb $'9,%al
  7965. ja ok_cur
  7966. movb $'~,%ah
  7967. ok_cur: shll $16,%eax
  7968. movw $0x5b1b,%ax
  7969. xorl %ebx,%ebx
  7970. jmp put_queue
  7971.  
  7972. num_table:
  7973. .ascii "789 456 1230,"
  7974. cur_table:
  7975. .ascii "HA5 DGC YB623"
  7976.  
  7977. /*
  7978. * this routine handles function keys
  7979. */
  7980. func:
  7981. subb $0x3B,%al
  7982. jb end_func
  7983. cmpb $9,%al
  7984. jbe ok_func
  7985. subb $18,%al
  7986. cmpb $10,%al
  7987. jb end_func
  7988. cmpb $11,%al
  7989. ja end_func
  7990. ok_func:
  7991. cmpl $4,%ecx /* check that there is enough room */
  7992. jl end_func
  7993. movl func_table(,%eax,4),%eax
  7994. xorl %ebx,%ebx
  7995. jmp put_queue
  7996. end_func:
  7997. ret
  7998.  
  7999. /*
  8000. * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
  8001. */
  8002. func_table:
  8003. .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
  8004. .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
  8005. .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
  8006.  
  8007. key_map:
  8008. .byte 0,27
  8009. .ascii "1234567890+'"
  8010. .byte 127,9
  8011. .ascii "qwertyuiop}"
  8012. .byte 0,10,0
  8013. .ascii "asdfghjkl|{"
  8014. .byte 0,0
  8015. .ascii "'zxcvbnm,.-"
  8016. .byte 0,'*,0,32 /* 36-39 */
  8017. .fill 16,1,0 /* 3A-49 */
  8018. .byte '-,0,0,0,'+ /* 4A-4E */
  8019. .byte 0,0,0,0,0,0,0 /* 4F-55 */
  8020. .byte '<
  8021. .fill 10,1,0
  8022.  
  8023. shift_map:
  8024. .byte 0,27
  8025. .ascii "!\"#$%&/()=?`"
  8026. .byte 127,9
  8027. .ascii "QWERTYUIOP]^"
  8028. .byte 10,0
  8029. .ascii "ASDFGHJKL\\["
  8030. .byte 0,0
  8031. .ascii "*ZXCVBNM;:_"
  8032. .byte 0,'*,0,32 /* 36-39 */
  8033. .fill 16,1,0 /* 3A-49 */
  8034. .byte '-,0,0,0,'+ /* 4A-4E */
  8035. .byte 0,0,0,0,0,0,0 /* 4F-55 */
  8036. .byte '>
  8037. .fill 10,1,0
  8038.  
  8039. alt_map:
  8040. .byte 0,0
  8041. .ascii "\0@\0$\0\0{[]}\\\0"
  8042. .byte 0,0
  8043. .byte 0,0,0,0,0,0,0,0,0,0,0
  8044. .byte '~,10,0
  8045. .byte 0,0,0,0,0,0,0,0,0,0,0
  8046. .byte 0,0
  8047. .byte 0,0,0,0,0,0,0,0,0,0,0
  8048. .byte 0,0,0,0 /* 36-39 */
  8049. .fill 16,1,0 /* 3A-49 */
  8050. .byte 0,0,0,0,0 /* 4A-4E */
  8051. .byte 0,0,0,0,0,0,0 /* 4F-55 */
  8052. .byte '|
  8053. .fill 10,1,0
  8054.  
  8055. /*
  8056. * do_self handles "normal" keys, ie keys that don't change meaning
  8057. * and which have just one character returns.
  8058. */
  8059. do_self:
  8060. lea alt_map,%ebx
  8061. testb $0x20,mode /* alt-gr */
  8062. jne 1f
  8063. lea shift_map,%ebx
  8064. testb $0x03,mode
  8065. jne 1f
  8066. lea key_map,%ebx
  8067. 1: movb (%ebx,%eax),%al
  8068. orb %al,%al
  8069. je none
  8070. testb $0x4c,mode /* ctrl or caps */
  8071. je 2f
  8072. cmpb $'a,%al
  8073. jb 2f
  8074. cmpb $'z,%al
  8075. ja 2f
  8076. subb $32,%al
  8077. 2: testb $0x0c,mode /* ctrl */
  8078. je 3f
  8079. cmpb $64,%al
  8080. jb 3f
  8081. cmpb $64+32,%al
  8082. jae 3f
  8083. subb $64,%al
  8084. 3: testb $0x10,mode /* left alt */
  8085. je 4f
  8086. orb $0x80,%al
  8087. 4: andl $0xff,%eax
  8088. xorl %ebx,%ebx
  8089. call put_queue
  8090. none: ret
  8091.  
  8092. /*
  8093. * minus has a routine of it's own, as a 'E0h' before
  8094. * the scan code for minus means that the numeric keypad
  8095. * slash was pushed.
  8096. */
  8097. minus: cmpb $1,e0
  8098. jne do_self
  8099. movl $'/,%eax
  8100. xorl %ebx,%ebx
  8101. jmp put_queue
  8102.  
  8103. /*
  8104. * This table decides which routine to call when a scan-code has been
  8105. * gotten. Most routines just call do_self, or none, depending if
  8106. * they are make or break.
  8107. */
  8108. key_table:
  8109. .long none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */
  8110. .long do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */
  8111. .long do_self,do_self,do_self,do_self /* 08-0B 7 8 9 0 */
  8112. .long do_self,do_self,do_self,do_self /* 0C-0F + ' bs tab */
  8113. .long do_self,do_self,do_self,do_self /* 10-13 q w e r */
  8114. .long do_self,do_self,do_self,do_self /* 14-17 t y u i */
  8115. .long do_self,do_self,do_self,do_self /* 18-1B o p } ^ */
  8116. .long do_self,ctrl,do_self,do_self /* 1C-1F enter ctrl a s */
  8117. .long do_self,do_self,do_self,do_self /* 20-23 d f g h */
  8118. .long do_self,do_self,do_self,do_self /* 24-27 j k l | */
  8119. .long do_self,do_self,lshift,do_self /* 28-2B { para lshift , */
  8120. .long do_self,do_self,do_self,do_self /* 2C-2F z x c v */
  8121. .long do_self,do_self,do_self,do_self /* 30-33 b n m , */
  8122. .long do_self,minus,rshift,do_self /* 34-37 . - rshift * */
  8123. .long alt,do_self,caps,func /* 38-3B alt sp caps f1 */
  8124. .long func,func,func,func /* 3C-3F f2 f3 f4 f5 */
  8125. .long func,func,func,func /* 40-43 f6 f7 f8 f9 */
  8126. .long func,num,scroll,cursor /* 44-47 f10 num scr home */
  8127. .long cursor,cursor,do_self,cursor /* 48-4B up pgup - left */
  8128. .long cursor,cursor,do_self,cursor /* 4C-4F n5 right + end */
  8129. .long cursor,cursor,cursor,cursor /* 50-53 dn pgdn ins del */
  8130. .long none,none,do_self,func /* 54-57 sysreq ? < f11 */
  8131. .long func,none,none,none /* 58-5B f12 ? ? ? */
  8132. .long none,none,none,none /* 5C-5F ? ? ? ? */
  8133. .long none,none,none,none /* 60-63 ? ? ? ? */
  8134. .long none,none,none,none /* 64-67 ? ? ? ? */
  8135. .long none,none,none,none /* 68-6B ? ? ? ? */
  8136. .long none,none,none,none /* 6C-6F ? ? ? ? */
  8137. .long none,none,none,none /* 70-73 ? ? ? ? */
  8138. .long none,none,none,none /* 74-77 ? ? ? ? */
  8139. .long none,none,none,none /* 78-7B ? ? ? ? */
  8140. .long none,none,none,none /* 7C-7F ? ? ? ? */
  8141. .long none,none,none,none /* 80-83 ? br br br */
  8142. .long none,none,none,none /* 84-87 br br br br */
  8143. .long none,none,none,none /* 88-8B br br br br */
  8144. .long none,none,none,none /* 8C-8F br br br br */
  8145. .long none,none,none,none /* 90-93 br br br br */
  8146. .long none,none,none,none /* 94-97 br br br br */
  8147. .long none,none,none,none /* 98-9B br br br br */
  8148. .long none,unctrl,none,none /* 9C-9F br unctrl br br */
  8149. .long none,none,none,none /* A0-A3 br br br br */
  8150. .long none,none,none,none /* A4-A7 br br br br */
  8151. .long none,none,unlshift,none /* A8-AB br br unlshift br */
  8152. .long none,none,none,none /* AC-AF br br br br */
  8153. .long none,none,none,none /* B0-B3 br br br br */
  8154. .long none,none,unrshift,none /* B4-B7 br br unrshift br */
  8155. .long unalt,none,uncaps,none /* B8-BB unalt br uncaps br */
  8156. .long none,none,none,none /* BC-BF br br br br */
  8157. .long none,none,none,none /* C0-C3 br br br br */
  8158. .long none,none,none,none /* C4-C7 br br br br */
  8159. .long none,none,none,none /* C8-CB br br br br */
  8160. .long none,none,none,none /* CC-CF br br br br */
  8161. .long none,none,none,none /* D0-D3 br br br br */
  8162. .long none,none,none,none /* D4-D7 br br br br */
  8163. .long none,none,none,none /* D8-DB br ? ? ? */
  8164. .long none,none,none,none /* DC-DF ? ? ? ? */
  8165. .long none,none,none,none /* E0-E3 e0 e1 ? ? */
  8166. .long none,none,none,none /* E4-E7 ? ? ? ? */
  8167. .long none,none,none,none /* E8-EB ? ? ? ? */
  8168. .long none,none,none,none /* EC-EF ? ? ? ? */
  8169. .long none,none,none,none /* F0-F3 ? ? ? ? */
  8170. .long none,none,none,none /* F4-F7 ? ? ? ? */
  8171. .long none,none,none,none /* F8-FB ? ? ? ? */
  8172. .long none,none,none,none /* FC-FF ? ? ? ? */
  8173.  
  8174. /*
  8175. * kb_wait waits for the keyboard controller buffer to empty.
  8176. * there is no timeout - if the buffer doesn't empty, we hang.
  8177. */
  8178. kb_wait:
  8179. pushl %eax
  8180. 1: inb $0x64,%al
  8181. testb $0x02,%al
  8182. jne 1b
  8183. popl %eax
  8184. ret
  8185. /*
  8186. * This routine reboots the machine by asking the keyboard
  8187. * controller to pulse the reset-line low.
  8188. */
  8189. reboot:
  8190. call kb_wait
  8191. movw $0x1234,0x472 /* don't do memory check */
  8192. movb $0xfc,%al /* pulse reset and A20 low */
  8193. outb %al,$0x64
  8194. die: jmp die
  8195.  
  8196. ------------------------------------------------------------------------
  8197.  
  8198. kernel/Makefile
  8199.  
  8200. #
  8201. # Makefile for the FREAX-kernel.
  8202. #
  8203. # Note! Dependencies are done automagically by 'make dep', which also
  8204. # removes any old dependencies. DON'T put your own dependencies here
  8205. # unless it's something special (ie not a .c file).
  8206. #
  8207.  
  8208. AR =gar
  8209. AS =gas
  8210. LD =gld
  8211. LDFLAGS =-s -x
  8212. CC =gcc
  8213. CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
  8214. -finline-functions -mstring-insns -nostdinc -I../include
  8215. CPP =gcc -E -nostdinc -I../include
  8216.  
  8217. .c.s:
  8218. $(CC) $(CFLAGS) \
  8219. -S -o $*.s $<
  8220. .s.o:
  8221. $(AS) -c -o $*.o $<
  8222. .c.o:
  8223. $(CC) $(CFLAGS) \
  8224. -c -o $*.o $<
  8225.  
  8226. OBJS = sched.o system_call.o traps.o asm.o fork.o \
  8227. panic.o printk.o vsprintf.o tty_io.o console.o \
  8228. keyboard.o rs_io.o hd.o sys.o exit.o serial.o \
  8229. mktime.o
  8230.  
  8231. kernel.o: $(OBJS)
  8232. $(LD) -r -o kernel.o $(OBJS)
  8233. sync
  8234.  
  8235. clean:
  8236. rm -f core *.o *.a tmp_make
  8237. for i in *.c;do rm -f `basename $$i .c`.s;done
  8238.  
  8239. dep:
  8240. sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
  8241. (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
  8242. $(CPP) -M $$i;done) >> tmp_make
  8243. cp tmp_make Makefile
  8244.  
  8245. ### Dependencies:
  8246. console.s console.o : console.c ../include/linux/sched.h ../include/linux/head.h \
  8247. ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
  8248. ../include/linux/tty.h ../include/termios.h ../include/asm/io.h \
  8249. ../include/asm/system.h
  8250. exit.s exit.o : exit.c ../include/errno.h ../include/signal.h \
  8251. ../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
  8252. ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
  8253. ../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
  8254. ../include/asm/segment.h
  8255. fork.s fork.o : fork.c ../include/errno.h ../include/linux/sched.h \
  8256. ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
  8257. ../include/linux/mm.h ../include/linux/kernel.h ../include/asm/segment.h \
  8258. ../include/asm/system.h
  8259. hd.s hd.o : hd.c ../include/linux/config.h ../include/linux/sched.h \
  8260. ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
  8261. ../include/linux/mm.h ../include/linux/kernel.h ../include/linux/hdreg.h \
  8262. ../include/asm/system.h ../include/asm/io.h ../include/asm/segment.h
  8263. mktime.s mktime.o : mktime.c ../include/time.h
  8264. panic.s panic.o : panic.c ../include/linux/kernel.h
  8265. printk.s printk.o : printk.c ../include/stdarg.h ../include/stddef.h \
  8266. ../include/linux/kernel.h
  8267. sched.s sched.o : sched.c ../include/linux/sched.h ../include/linux/head.h \
  8268. ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
  8269. ../include/linux/kernel.h ../include/signal.h ../include/linux/sys.h \
  8270. ../include/asm/system.h ../include/asm/io.h ../include/asm/segment.h
  8271. serial.s serial.o : serial.c ../include/linux/tty.h ../include/termios.h \
  8272. ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
  8273. ../include/sys/types.h ../include/linux/mm.h ../include/asm/system.h \
  8274. ../include/asm/io.h
  8275. sys.s sys.o : sys.c ../include/errno.h ../include/linux/sched.h \
  8276. ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
  8277. ../include/linux/mm.h ../include/linux/tty.h ../include/termios.h \
  8278. ../include/linux/kernel.h ../include/asm/segment.h ../include/sys/times.h \
  8279. ../include/sys/utsname.h
  8280. traps.s traps.o : traps.c ../include/string.h ../include/linux/head.h \
  8281. ../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
  8282. ../include/linux/mm.h ../include/linux/kernel.h ../include/asm/system.h \
  8283. ../include/asm/segment.h
  8284. tty_io.s tty_io.o : tty_io.c ../include/ctype.h ../include/errno.h \
  8285. ../include/signal.h ../include/sys/types.h ../include/linux/sched.h \
  8286. ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
  8287. ../include/linux/tty.h ../include/termios.h ../include/asm/segment.h \
  8288. ../include/asm/system.h
  8289. vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/string.h
  8290.  
  8291. ------------------------------------------------------------------------
  8292.  
  8293. kernel/mktime.c
  8294.  
  8295. #include <time.h>
  8296.  
  8297. /*
  8298. * This isn't the library routine, it is only used in the kernel.
  8299. * as such, we don't care about years<1970 etc, but assume everything
  8300. * is ok. Similarly, TZ etc is happily ignored. We just do everything
  8301. * as easily as possible. Let's find something public for the library
  8302. * routines (although I think minix times is public).
  8303. */
  8304. /*
  8305. * PS. I hate whoever though up the year 1970 - couldn't they have gotten
  8306. * a leap-year instead? I also hate Gregorius, pope or no. I'm grumpy.
  8307. */
  8308. #define MINUTE 60
  8309. #define HOUR (60*MINUTE)
  8310. #define DAY (24*HOUR)
  8311. #define YEAR (365*DAY)
  8312.  
  8313. /* interestingly, we assume leap-years */
  8314. static int month[12] = {
  8315. 0,
  8316. DAY*(31),
  8317. DAY*(31+29),
  8318. DAY*(31+29+31),
  8319. DAY*(31+29+31+30),
  8320. DAY*(31+29+31+30+31),
  8321. DAY*(31+29+31+30+31+30),
  8322. DAY*(31+29+31+30+31+30+31),
  8323. DAY*(31+29+31+30+31+30+31+31),
  8324. DAY*(31+29+31+30+31+30+31+31+30),
  8325. DAY*(31+29+31+30+31+30+31+31+30+31),
  8326. DAY*(31+29+31+30+31+30+31+31+30+31+30)
  8327. };
  8328.  
  8329. long kernel_mktime(struct tm * tm)
  8330. {
  8331. long res;
  8332. int year;
  8333.  
  8334. year = tm->tm_year - 70;
  8335. /* magic offsets (y+1) needed to get leapyears right.*/
  8336. res = YEAR*year + DAY*((year+1)/4);
  8337. res += month[tm->tm_mon];
  8338. /* and (y+2) here. If it wasn't a leap-year, we have to adjust */
  8339. if (tm->tm_mon>1 && ((year+2)%4))
  8340. res -= DAY;
  8341. res += DAY*(tm->tm_mday-1);
  8342. res += HOUR*tm->tm_hour;
  8343. res += MINUTE*tm->tm_min;
  8344. res += tm->tm_sec;
  8345. return res;
  8346. }
  8347.  
  8348. ------------------------------------------------------------------------
  8349.  
  8350. kernel/panic.c
  8351.  
  8352. /*
  8353. * This function is used through-out the kernel (includeinh mm and fs)
  8354. * to indicate a major problem.
  8355. */
  8356. #include <linux/kernel.h>
  8357.  
  8358. volatile void panic(const char * s)
  8359. {
  8360. printk("Kernel panic: %s\n\r",s);
  8361. for(;;);
  8362. }
  8363.  
  8364. ------------------------------------------------------------------------
  8365.  
  8366. kernel/printk.c
  8367.  
  8368. /*
  8369. * When in kernel-mode, we cannot use printf, as fs is liable to
  8370. * point to 'interesting' things. Make a printf with fs-saving, and
  8371. * all is well.
  8372. */
  8373. #include <stdarg.h>
  8374. #include <stddef.h>
  8375.  
  8376. #include <linux/kernel.h>
  8377.  
  8378. static char buf[1024];
  8379.  
  8380. int printk(const char *fmt, ...)
  8381. {
  8382. va_list args;
  8383. int i;
  8384.  
  8385. va_start(args, fmt);
  8386. i=vsprintf(buf,fmt,args);
  8387. va_end(args);
  8388. __asm__("push %%fs\n\t"
  8389. "push %%ds\n\t"
  8390. "pop %%fs\n\t"
  8391. "pushl %0\n\t"
  8392. "pushl $_buf\n\t"
  8393. "pushl $0\n\t"
  8394. "call _tty_write\n\t"
  8395. "addl $8,%%esp\n\t"
  8396. "popl %0\n\t"
  8397. "pop %%fs"
  8398. ::"r" (i):"ax","cx","dx");
  8399. return i;
  8400. }
  8401.  
  8402. ------------------------------------------------------------------------
  8403.  
  8404. kernel/rs_io.s
  8405.  
  8406. /*
  8407. * rs_io.s
  8408. *
  8409. * This module implements the rs232 io interrupts.
  8410. */
  8411.  
  8412. .text
  8413. .globl _rs1_interrupt,_rs2_interrupt
  8414.  
  8415. size = 1024 /* must be power of two !
  8416. and must match the value
  8417. in tty_io.c!!! */
  8418.  
  8419. /* these are the offsets into the read/write buffer structures */
  8420. rs_addr = 0
  8421. head = 4
  8422. tail = 8
  8423. proc_list = 12
  8424. buf = 16
  8425.  
  8426. startup = 256 /* chars left in write queue when we restart it */
  8427.  
  8428. /*
  8429. * These are the actual interrupt routines. They look where
  8430. * the interrupt is coming from, and take appropriate action.
  8431. */
  8432. .align 2
  8433. _rs1_interrupt:
  8434. pushl $_table_list+8
  8435. jmp rs_int
  8436. .align 2
  8437. _rs2_interrupt:
  8438. pushl $_table_list+16
  8439. rs_int:
  8440. pushl %edx
  8441. pushl %ecx
  8442. pushl %ebx
  8443. pushl %eax
  8444. push %es
  8445. push %ds /* as this is an interrupt, we cannot */
  8446. pushl $0x10 /* know that bs is ok. Load it */
  8447. pop %ds
  8448. pushl $0x10
  8449. pop %es
  8450. movl 24(%esp),%edx
  8451. movl (%edx),%edx
  8452. movl rs_addr(%edx),%edx
  8453. addl $2,%edx /* interrupt ident. reg */
  8454. rep_int:
  8455. xorl %eax,%eax
  8456. inb %dx,%al
  8457. testb $1,%al
  8458. jne end
  8459. cmpb $6,%al /* this shouldn't happen, but ... */
  8460. ja end
  8461. movl 24(%esp),%ecx
  8462. pushl %edx
  8463. subl $2,%edx
  8464. call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
  8465. popl %edx
  8466. jmp rep_int
  8467. end: movb $0x20,%al
  8468. outb %al,$0x20 /* EOI */
  8469. pop %ds
  8470. pop %es
  8471. popl %eax
  8472. popl %ebx
  8473. popl %ecx
  8474. popl %edx
  8475. addl $4,%esp # jump over _table_list entry
  8476. iret
  8477.  
  8478. jmp_table:
  8479. .long modem_status,write_char,read_char,line_status
  8480.  
  8481. .align 2
  8482. modem_status:
  8483. addl $6,%edx /* clear intr by reading modem status reg */
  8484. inb %dx,%al
  8485. ret
  8486.  
  8487. .align 2
  8488. line_status:
  8489. addl $5,%edx /* clear intr by reading line status reg. */
  8490. inb %dx,%al
  8491. ret
  8492.  
  8493. .align 2
  8494. read_char:
  8495. inb %dx,%al
  8496. movl %ecx,%edx
  8497. subl $_table_list,%edx
  8498. shrl $3,%edx
  8499. movl (%ecx),%ecx # read-queue
  8500. movl head(%ecx),%ebx
  8501. movb %al,buf(%ecx,%ebx)
  8502. incl %ebx
  8503. andl $size-1,%ebx
  8504. cmpl tail(%ecx),%ebx
  8505. je 1f
  8506. movl %ebx,head(%ecx)
  8507. pushl %edx
  8508. call _do_tty_interrupt
  8509. addl $4,%esp
  8510. 1: ret
  8511.  
  8512. .align 2
  8513. write_char:
  8514. movl 4(%ecx),%ecx # write-queue
  8515. movl head(%ecx),%ebx
  8516. subl tail(%ecx),%ebx
  8517. andl $size-1,%ebx # nr chars in queue
  8518. je write_buffer_empty
  8519. cmpl $startup,%ebx
  8520. ja 1f
  8521. movl proc_list(%ecx),%ebx # wake up sleeping process
  8522. testl %ebx,%ebx # is there any?
  8523. je 1f
  8524. movl $0,(%ebx)
  8525. 1: movl tail(%ecx),%ebx
  8526. movb buf(%ecx,%ebx),%al
  8527. outb %al,%dx
  8528. incl %ebx
  8529. andl $size-1,%ebx
  8530. movl %ebx,tail(%ecx)
  8531. cmpl head(%ecx),%ebx
  8532. je write_buffer_empty
  8533. ret
  8534. .align 2
  8535. write_buffer_empty:
  8536. movl proc_list(%ecx),%ebx # wake up sleeping process
  8537. testl %ebx,%ebx # is there any?
  8538. je 1f
  8539. movl $0,(%ebx)
  8540. 1: incl %edx
  8541. inb %dx,%al
  8542. jmp 1f
  8543. 1: jmp 1f
  8544. 1: andb $0xd,%al /* disable transmit interrupt */
  8545. outb %al,%dx
  8546. ret
  8547.  
  8548. ------------------------------------------------------------------------
  8549.  
  8550. kernel/sched.c
  8551.  
  8552. /*
  8553. * 'sched.c' is the main kernel file. It contains scheduling primitives
  8554. * (sleep_on, wakeup, schedule etc) as well as a number of simple system
  8555. * call functions (type getpid(), which just extracts a field from
  8556. * current-task
  8557. */
  8558. #include <linux/sched.h>
  8559. #include <linux/kernel.h>
  8560. #include <signal.h>
  8561. #include <linux/sys.h>
  8562. #include <asm/system.h>
  8563. #include <asm/io.h>
  8564. #include <asm/segment.h>
  8565.  
  8566. #define LATCH (1193180/HZ)
  8567.  
  8568. extern void mem_use(void);
  8569.  
  8570. extern int timer_interrupt(void);
  8571. extern int system_call(void);
  8572.  
  8573. union task_union {
  8574. struct task_struct task;
  8575. char stack[PAGE_SIZE];
  8576. };
  8577.  
  8578. static union task_union init_task = {INIT_TASK,};
  8579.  
  8580. long volatile jiffies=0;
  8581. long startup_time=0;
  8582. struct task_struct *current = &(init_task.task), *last_task_used_math = NULL;
  8583.  
  8584. struct task_struct * task[NR_TASKS] = {&(init_task.task), };
  8585.  
  8586. long user_stack [ PAGE_SIZE>>2 ] ;
  8587.  
  8588. struct {
  8589. long * a;
  8590. short b;
  8591. } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
  8592. /*
  8593. * 'math_state_restore()' saves the current math information in the
  8594. * old math state array, and gets the new ones from the current task
  8595. */
  8596. void math_state_restore()
  8597. {
  8598. if (last_task_used_math)
  8599. __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
  8600. if (current->used_math)
  8601. __asm__("frstor %0"::"m" (current->tss.i387));
  8602. else {
  8603. __asm__("fninit"::);
  8604. current->used_math=1;
  8605. }
  8606. last_task_used_math=current;
  8607. }
  8608.  
  8609. /*
  8610. * 'schedule()' is the scheduler function. This is GOOD CODE! There
  8611. * probably won't be any reason to change this, as it should work well
  8612. * in all circumstances (ie gives IO-bound processes good response etc).
  8613. * The one thing you might take a look at is the signal-handler code here.
  8614. *
  8615. * NOTE!! Task 0 is the 'idle' task, which gets called when no other
  8616. * tasks can run. It can not be killed, and it cannot sleep. The 'state'
  8617. * information in task[0] is never used.
  8618. */
  8619. void schedule(void)
  8620. {
  8621. int i,next,c;
  8622. struct task_struct ** p;
  8623.  
  8624. /* check alarm, wake up any interruptible tasks that have got a signal */
  8625.  
  8626. for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
  8627. if (*p) {
  8628. if ((*p)->alarm && (*p)->alarm < jiffies) {
  8629. (*p)->signal |= (1<<(SIGALRM-1));
  8630. (*p)->alarm = 0;
  8631. }
  8632. if ((*p)->signal && (*p)->state==TASK_INTERRUPTIBLE)
  8633. (*p)->state=TASK_RUNNING;
  8634. }
  8635.  
  8636. /* this is the scheduler proper: */
  8637.  
  8638. while (1) {
  8639. c = -1;
  8640. next = 0;
  8641. i = NR_TASKS;
  8642. p = &task[NR_TASKS];
  8643. while (--i) {
  8644. if (!*--p)
  8645. continue;
  8646. if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
  8647. c = (*p)->counter, next = i;
  8648. }
  8649. if (c) break;
  8650. for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
  8651. if (*p)
  8652. (*p)->counter = ((*p)->counter >> 1) +
  8653. (*p)->priority;
  8654. }
  8655. switch_to(next);
  8656. }
  8657.  
  8658. int sys_pause(void)
  8659. {
  8660. current->state = TASK_INTERRUPTIBLE;
  8661. schedule();
  8662. return 0;
  8663. }
  8664.  
  8665. void sleep_on(struct task_struct **p)
  8666. {
  8667. struct task_struct *tmp;
  8668.  
  8669. if (!p)
  8670. return;
  8671. if (current == &(init_task.task))
  8672. panic("task[0] trying to sleep");
  8673. tmp = *p;
  8674. *p = current;
  8675. current->state = TASK_UNINTERRUPTIBLE;
  8676. schedule();
  8677. if (tmp)
  8678. tmp->state=0;
  8679. }
  8680.  
  8681. void interruptible_sleep_on(struct task_struct **p)
  8682. {
  8683. struct task_struct *tmp;
  8684.  
  8685. if (!p)
  8686. return;
  8687. if (current == &(init_task.task))
  8688. panic("task[0] trying to sleep");
  8689. tmp=*p;
  8690. *p=current;
  8691. repeat: current->state = TASK_INTERRUPTIBLE;
  8692. schedule();
  8693. if (*p && *p != current) {
  8694. (**p).state=0;
  8695. goto repeat;
  8696. }
  8697. *p=NULL;
  8698. if (tmp)
  8699. tmp->state=0;
  8700. }
  8701.  
  8702. void wake_up(struct task_struct **p)
  8703. {
  8704. if (p && *p) {
  8705. (**p).state=0;
  8706. *p=NULL;
  8707. }
  8708. }
  8709.  
  8710. void do_timer(long cpl)
  8711. {
  8712. if (cpl)
  8713. current->utime++;
  8714. else
  8715. current->stime++;
  8716. if ((--current->counter)>0) return;
  8717. current->counter=0;
  8718. if (!cpl) return;
  8719. schedule();
  8720. }
  8721.  
  8722. int sys_alarm(long seconds)
  8723. {
  8724. current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
  8725. return seconds;
  8726. }
  8727.  
  8728. int sys_getpid(void)
  8729. {
  8730. return current->pid;
  8731. }
  8732.  
  8733. int sys_getppid(void)
  8734. {
  8735. return current->father;
  8736. }
  8737.  
  8738. int sys_getuid(void)
  8739. {
  8740. return current->uid;
  8741. }
  8742.  
  8743. int sys_geteuid(void)
  8744. {
  8745. return current->euid;
  8746. }
  8747.  
  8748. int sys_getgid(void)
  8749. {
  8750. return current->gid;
  8751. }
  8752.  
  8753. int sys_getegid(void)
  8754. {
  8755. return current->egid;
  8756. }
  8757.  
  8758. int sys_nice(long increment)
  8759. {
  8760. if (current->priority-increment>0)
  8761. current->priority -= increment;
  8762. return 0;
  8763. }
  8764.  
  8765. int sys_signal(long signal,long addr,long restorer)
  8766. {
  8767. long i;
  8768.  
  8769. switch (signal) {
  8770. case SIGHUP: case SIGINT: case SIGQUIT: case SIGILL:
  8771. case SIGTRAP: case SIGABRT: case SIGFPE: case SIGUSR1:
  8772. case SIGSEGV: case SIGUSR2: case SIGPIPE: case SIGALRM:
  8773. case SIGCHLD:
  8774. i=(long) current->sig_fn[signal-1];
  8775. current->sig_fn[signal-1] = (fn_ptr) addr;
  8776. current->sig_restorer = (fn_ptr) restorer;
  8777. return i;
  8778. default: return -1;
  8779. }
  8780. }
  8781.  
  8782. void sched_init(void)
  8783. {
  8784. int i;
  8785. struct desc_struct * p;
  8786.  
  8787. set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
  8788. set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
  8789. p = gdt+2+FIRST_TSS_ENTRY;
  8790. for(i=1;i<NR_TASKS;i++) {
  8791. task[i] = NULL;
  8792. p->a=p->b=0;
  8793. p++;
  8794. p->a=p->b=0;
  8795. p++;
  8796. }
  8797. ltr(0);
  8798. lldt(0);
  8799. outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */
  8800. outb_p(LATCH & 0xff , 0x40); /* LSB */
  8801. outb(LATCH >> 8 , 0x40); /* MSB */
  8802. set_intr_gate(0x20,&timer_interrupt);
  8803. outb(inb_p(0x21)&~0x01,0x21);
  8804. set_system_gate(0x80,&system_call);
  8805. }
  8806.  
  8807. ------------------------------------------------------------------------
  8808.  
  8809. kernel/serial.c
  8810.  
  8811. /*
  8812. * serial.c
  8813. *
  8814. * This module implements the rs232 io functions
  8815. * void rs_write(struct tty_struct * queue);
  8816. * void rs_init(void);
  8817. * and all interrupts pertaining to serial IO.
  8818. */
  8819.  
  8820. #include <linux/tty.h>
  8821. #include <linux/sched.h>
  8822. #include <asm/system.h>
  8823. #include <asm/io.h>
  8824.  
  8825. #define WAKEUP_CHARS (TTY_BUF_SIZE/4)
  8826.  
  8827. extern void rs1_interrupt(void);
  8828. extern void rs2_interrupt(void);
  8829.  
  8830. static void init(int port)
  8831. {
  8832. outb_p(0x80,port+3); /* set DLAB of line control reg */
  8833. outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps */
  8834. outb_p(0x00,port+1); /* MS of divisor */
  8835. outb_p(0x03,port+3); /* reset DLAB */
  8836. outb_p(0x0b,port+4); /* set DTR,RTS, OUT_2 */
  8837. outb_p(0x0d,port+1); /* enable all intrs but writes */
  8838. (void)inb(port); /* read data port to reset things (?) */
  8839. }
  8840.  
  8841. void rs_init(void)
  8842. {
  8843. set_intr_gate(0x24,rs1_interrupt);
  8844. set_intr_gate(0x23,rs2_interrupt);
  8845. init(tty_table[1].read_q.data);
  8846. init(tty_table[2].read_q.data);
  8847. outb(inb_p(0x21)&0xE7,0x21);
  8848. }
  8849.  
  8850. /*
  8851. * This routine gets called when tty_write has put something into
  8852. * the write_queue. It must check wheter the queue is empty, and
  8853. * set the interrupt register accordingly
  8854. *
  8855. * void _rs_write(struct tty_struct * tty);
  8856. */
  8857. void rs_write(struct tty_struct * tty)
  8858. {
  8859. cli();
  8860. if (!EMPTY(tty->write_q))
  8861. outb(inb_p(tty->write_q.data+1)|0x02,tty->write_q.data+1);
  8862. sti();
  8863. }
  8864.  
  8865. ------------------------------------------------------------------------
  8866.  
  8867. kernel/sys.c
  8868.  
  8869. #include <errno.h>
  8870.  
  8871. #include <linux/sched.h>
  8872. #include <linux/tty.h>
  8873. #include <linux/kernel.h>
  8874. #include <asm/segment.h>
  8875. #include <sys/times.h>
  8876. #include <sys/utsname.h>
  8877.  
  8878. int sys_ftime()
  8879. {
  8880. return -ENOSYS;
  8881. }
  8882.  
  8883. int sys_mknod()
  8884. {
  8885. return -ENOSYS;
  8886. }
  8887.  
  8888. int sys_break()
  8889. {
  8890. return -ENOSYS;
  8891. }
  8892.  
  8893. int sys_mount()
  8894. {
  8895. return -ENOSYS;
  8896. }
  8897.  
  8898. int sys_umount()
  8899. {
  8900. return -ENOSYS;
  8901. }
  8902.  
  8903. int sys_ustat(int dev,struct ustat * ubuf)
  8904. {
  8905. return -1;
  8906. }
  8907.  
  8908. int sys_ptrace()
  8909. {
  8910. return -ENOSYS;
  8911. }
  8912.  
  8913. int sys_stty()
  8914. {
  8915. return -ENOSYS;
  8916. }
  8917.  
  8918. int sys_gtty()
  8919. {
  8920. return -ENOSYS;
  8921. }
  8922.  
  8923. int sys_rename()
  8924. {
  8925. return -ENOSYS;
  8926. }
  8927.  
  8928. int sys_prof()
  8929. {
  8930. return -ENOSYS;
  8931. }
  8932.  
  8933. int sys_setgid(int gid)
  8934. {
  8935. if (current->euid && current->uid)
  8936. if (current->gid==gid || current->sgid==gid)
  8937. current->egid=gid;
  8938. else
  8939. return -EPERM;
  8940. else
  8941. current->gid=current->egid=gid;
  8942. return 0;
  8943. }
  8944.  
  8945. int sys_acct()
  8946. {
  8947. return -ENOSYS;
  8948. }
  8949.  
  8950. int sys_phys()
  8951. {
  8952. return -ENOSYS;
  8953. }
  8954.  
  8955. int sys_lock()
  8956. {
  8957. return -ENOSYS;
  8958. }
  8959.  
  8960. int sys_mpx()
  8961. {
  8962. return -ENOSYS;
  8963. }
  8964.  
  8965. int sys_ulimit()
  8966. {
  8967. return -ENOSYS;
  8968. }
  8969.  
  8970. int sys_time(long * tloc)
  8971. {
  8972. int i;
  8973.  
  8974. i = CURRENT_TIME;
  8975. if (tloc) {
  8976. verify_area(tloc,4);
  8977. put_fs_long(i,(unsigned long *)tloc);
  8978. }
  8979. return i;
  8980. }
  8981.  
  8982. int sys_setuid(int uid)
  8983. {
  8984. if (current->euid && current->uid)
  8985. if (uid==current->uid || current->suid==current->uid)
  8986. current->euid=uid;
  8987. else
  8988. return -EPERM;
  8989. else
  8990. current->euid=current->uid=uid;
  8991. return 0;
  8992. }
  8993.  
  8994. int sys_stime(long * tptr)
  8995. {
  8996. if (current->euid && current->uid)
  8997. return -1;
  8998. startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
  8999. return 0;
  9000. }
  9001.  
  9002. int sys_times(struct tms * tbuf)
  9003. {
  9004. if (!tbuf)
  9005. return jiffies;
  9006. verify_area(tbuf,sizeof *tbuf);
  9007. put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
  9008. put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
  9009. put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
  9010. put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
  9011. return jiffies;
  9012. }
  9013.  
  9014. int sys_brk(unsigned long end_data_seg)
  9015. {
  9016. if (end_data_seg >= current->end_code &&
  9017. end_data_seg < current->start_stack - 16384)
  9018. current->brk = end_data_seg;
  9019. return current->brk;
  9020. }
  9021.  
  9022. /*
  9023. * This needs some heave checking ...
  9024. * I just haven't get the stomach for it. I also don't fully
  9025. * understand sessions/pgrp etc. Let somebody who does explain it.
  9026. */
  9027. int sys_setpgid(int pid, int pgid)
  9028. {
  9029. int i;
  9030.  
  9031. if (!pid)
  9032. pid = current->pid;
  9033. if (!pgid)
  9034. pgid = pid;
  9035. for (i=0 ; i<NR_TASKS ; i++)
  9036. if (task[i] && task[i]->pid==pid) {
  9037. if (task[i]->leader)
  9038. return -EPERM;
  9039. if (task[i]->session != current->session)
  9040. return -EPERM;
  9041. task[i]->pgrp = pgid;
  9042. return 0;
  9043. }
  9044. return -ESRCH;
  9045. }
  9046.  
  9047. int sys_getpgrp(void)
  9048. {
  9049. return current->pgrp;
  9050. }
  9051.  
  9052. int sys_setsid(void)
  9053. {
  9054. if (current->uid && current->euid)
  9055. return -EPERM;
  9056. if (current->leader)
  9057. return -EPERM;
  9058. current->leader = 1;
  9059. current->session = current->pgrp = current->pid;
  9060. current->tty = -1;
  9061. return current->pgrp;
  9062. }
  9063.  
  9064. int sys_uname(struct utsname * name)
  9065. {
  9066. static struct utsname thisname = {
  9067. "linux .0","nodename","release ","version ","machine "
  9068. };
  9069. int i;
  9070.  
  9071. if (!name) return -1;
  9072. verify_area(name,sizeof *name);
  9073. for(i=0;i<sizeof *name;i++)
  9074. put_fs_byte(((char *) &thisname)[i],i+(char *) name);
  9075. return (0);
  9076. }
  9077.  
  9078. int sys_umask(int mask)
  9079. {
  9080. int old = current->umask;
  9081.  
  9082. current->umask = mask & 0777;
  9083. return (old);
  9084. }
  9085.  
  9086. ------------------------------------------------------------------------
  9087.  
  9088. kernel/system_call.s
  9089.  
  9090. /*
  9091. * system_call.s contains the system-call low-level handling routines.
  9092. * This also contains the timer-interrupt handler, as some of the code is
  9093. * the same. The hd-interrupt is also here.
  9094. *
  9095. * NOTE: This code handles signal-recognition, which happens every time
  9096. * after a timer-interrupt and after each system call. Ordinary interrupts
  9097. * don't handle signal-recognition, as that would clutter them up totally
  9098. * unnecessarily.
  9099. *
  9100. * Stack layout in 'ret_from_system_call':
  9101. *
  9102. * 0(%esp) - %eax
  9103. * 4(%esp) - %ebx
  9104. * 8(%esp) - %ecx
  9105. * C(%esp) - %edx
  9106. * 10(%esp) - %fs
  9107. * 14(%esp) - %es
  9108. * 18(%esp) - %ds
  9109. * 1C(%esp) - %eip
  9110. * 20(%esp) - %cs
  9111. * 24(%esp) - %eflags
  9112. * 28(%esp) - %oldesp
  9113. * 2C(%esp) - %oldss
  9114. */
  9115.  
  9116. SIG_CHLD = 17
  9117. EAX = 0x00
  9118. EBX = 0x04
  9119. ECX = 0x08
  9120. EDX = 0x0C
  9121. FS = 0x10
  9122. ES = 0x14
  9123. DS = 0x18
  9124. EIP = 0x1C
  9125. CS = 0x20
  9126. EFLAGS = 0x24
  9127. OLDESP = 0x28
  9128. OLDSS = 0x2C
  9129.  
  9130. state = 0 # these are offsets into the task-struct.
  9131. counter = 4
  9132. priority = 8
  9133. signal = 12
  9134. restorer = 16 # address of info-restorer
  9135. sig_fn = 20 # table of 32 signal addresses
  9136.  
  9137. nr_system_calls = 67
  9138.  
  9139. .globl _system_call,_sys_fork,_timer_interrupt,_hd_interrupt,_sys_execve
  9140.  
  9141. .align 2
  9142. bad_sys_call:
  9143. movl $-1,%eax
  9144. iret
  9145. .align 2
  9146. reschedule:
  9147. pushl $ret_from_sys_call
  9148. jmp _schedule
  9149. .align 2
  9150. _system_call:
  9151. cmpl $nr_system_calls-1,%eax
  9152. ja bad_sys_call
  9153. push %ds
  9154. push %es
  9155. push %fs
  9156. pushl %edx
  9157. pushl %ecx # push %ebx,%ecx,%edx as parameters
  9158. pushl %ebx # to the system call
  9159. movl $0x10,%edx # set up ds,es to kernel space
  9160. mov %dx,%ds
  9161. mov %dx,%es
  9162. movl $0x17,%edx # fs points to local data space
  9163. mov %dx,%fs
  9164. call _sys_call_table(,%eax,4)
  9165. pushl %eax
  9166. movl _current,%eax
  9167. cmpl $0,state(%eax) # state
  9168. jne reschedule
  9169. cmpl $0,counter(%eax) # counter
  9170. je reschedule
  9171. ret_from_sys_call:
  9172. movl _current,%eax # task[0] cannot have signals
  9173. cmpl _task,%eax
  9174. je 3f
  9175. movl CS(%esp),%ebx # was old code segment supervisor
  9176. testl $3,%ebx # mode? If so - don't check signals
  9177. je 3f
  9178. cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
  9179. jne 3f
  9180. 2: movl signal(%eax),%ebx # signals (bitmap, 32 signals)
  9181. bsfl %ebx,%ecx # %ecx is signal nr, return if none
  9182. je 3f
  9183. btrl %ecx,%ebx # clear it
  9184. movl %ebx,signal(%eax)
  9185. movl sig_fn(%eax,%ecx,4),%ebx # %ebx is signal handler address
  9186. cmpl $1,%ebx
  9187. jb default_signal # 0 is default signal handler - exit
  9188. je 2b # 1 is ignore - find next signal
  9189. movl $0,sig_fn(%eax,%ecx,4) # reset signal handler address
  9190. incl %ecx
  9191. xchgl %ebx,EIP(%esp) # put new return address on stack
  9192. subl $28,OLDESP(%esp)
  9193. movl OLDESP(%esp),%edx # push old return address on stack
  9194. pushl %eax # but first check that it's ok.
  9195. pushl %ecx
  9196. pushl $28
  9197. pushl %edx
  9198. call _verify_area
  9199. popl %edx
  9200. addl $4,%esp
  9201. popl %ecx
  9202. popl %eax
  9203. movl restorer(%eax),%eax
  9204. movl %eax,%fs:(%edx) # flag/reg restorer
  9205. movl %ecx,%fs:4(%edx) # signal nr
  9206. movl EAX(%esp),%eax
  9207. movl %eax,%fs:8(%edx) # old eax
  9208. movl ECX(%esp),%eax
  9209. movl %eax,%fs:12(%edx) # old ecx
  9210. movl EDX(%esp),%eax
  9211. movl %eax,%fs:16(%edx) # old edx
  9212. movl EFLAGS(%esp),%eax
  9213. movl %eax,%fs:20(%edx) # old eflags
  9214. movl %ebx,%fs:24(%edx) # old return addr
  9215. 3: popl %eax
  9216. popl %ebx
  9217. popl %ecx
  9218. popl %edx
  9219. pop %fs
  9220. pop %es
  9221. pop %ds
  9222. iret
  9223.  
  9224. default_signal:
  9225. incl %ecx
  9226. cmpl $SIG_CHLD,%ecx
  9227. je 2b
  9228. pushl %ecx
  9229. call _do_exit # remember to set bit 7 when dumping core
  9230. addl $4,%esp
  9231. jmp 3b
  9232.  
  9233. .align 2
  9234. _timer_interrupt:
  9235. push %ds # save ds,es and put kernel data space
  9236. push %es # into them. %fs is used by _system_call
  9237. push %fs
  9238. pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
  9239. pushl %ecx # save those across function calls. %ebx
  9240. pushl %ebx # is saved as we use that in ret_sys_call
  9241. pushl %eax
  9242. movl $0x10,%eax
  9243. mov %ax,%ds
  9244. mov %ax,%es
  9245. movl $0x17,%eax
  9246. mov %ax,%fs
  9247. incl _jiffies
  9248. movb $0x20,%al # EOI to interrupt controller #1
  9249. outb %al,$0x20
  9250. movl CS(%esp),%eax
  9251. andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
  9252. pushl %eax
  9253. call _do_timer # 'do_timer(long CPL)' does everything from
  9254. addl $4,%esp # task switching to accounting ...
  9255. jmp ret_from_sys_call
  9256.  
  9257. .align 2
  9258. _sys_execve:
  9259. lea EIP(%esp),%eax
  9260. pushl %eax
  9261. call _do_execve
  9262. addl $4,%esp
  9263. ret
  9264.  
  9265. .align 2
  9266. _sys_fork:
  9267. call _find_empty_process
  9268. testl %eax,%eax
  9269. js 1f
  9270. push %gs
  9271. pushl %esi
  9272. pushl %edi
  9273. pushl %ebp
  9274. pushl %eax
  9275. call _copy_process
  9276. addl $20,%esp
  9277. 1: ret
  9278.  
  9279. _hd_interrupt:
  9280. pushl %eax
  9281. pushl %ecx
  9282. pushl %edx
  9283. push %ds
  9284. push %es
  9285. push %fs
  9286. movl $0x10,%eax
  9287. mov %ax,%ds
  9288. mov %ax,%es
  9289. movl $0x17,%eax
  9290. mov %ax,%fs
  9291. movb $0x20,%al
  9292. outb %al,$0x20 # EOI to interrupt controller #1
  9293. jmp 1f # give port chance to breathe
  9294. 1: jmp 1f
  9295. 1: outb %al,$0xA0 # same to controller #2
  9296. movl _do_hd,%eax
  9297. testl %eax,%eax
  9298. jne 1f
  9299. movl $_unexpected_hd_interrupt,%eax
  9300. 1: call *%eax # "interesting" way of handling intr.
  9301. pop %fs
  9302. pop %es
  9303. pop %ds
  9304. popl %edx
  9305. popl %ecx
  9306. popl %eax
  9307. iret
  9308.  
  9309.  
  9310. ------------------------------------------------------------------------
  9311.  
  9312. kernel/traps.c
  9313.  
  9314. /*
  9315. * 'Traps.c' handles hardware traps and faults after we have saved some
  9316. * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
  9317. * to mainly kill the offending process (probably by giving it a signal,
  9318. * but possibly by killing it outright if necessary).
  9319. */
  9320. #include <string.h>
  9321.  
  9322. #include <linux/head.h>
  9323. #include <linux/sched.h>
  9324. #include <linux/kernel.h>
  9325. #include <asm/system.h>
  9326. #include <asm/segment.h>
  9327.  
  9328. #define get_seg_byte(seg,addr) ({ \
  9329. register char __res; \
  9330. __asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
  9331. :"=a" (__res):"0" (seg),"m" (*(addr))); \
  9332. __res;})
  9333.  
  9334. #define get_seg_long(seg,addr) ({ \
  9335. register unsigned long __res; \
  9336. __asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \
  9337. :"=a" (__res):"0" (seg),"m" (*(addr))); \
  9338. __res;})
  9339.  
  9340. #define _fs() ({ \
  9341. register unsigned short __res; \
  9342. __asm__("mov %%fs,%%ax":"=a" (__res):); \
  9343. __res;})
  9344.  
  9345. int do_exit(long code);
  9346.  
  9347. void page_exception(void);
  9348.  
  9349. void divide_error(void);
  9350. void debug(void);
  9351. void nmi(void);
  9352. void int3(void);
  9353. void overflow(void);
  9354. void bounds(void);
  9355. void invalid_op(void);
  9356. void device_not_available(void);
  9357. void double_fault(void);
  9358. void coprocessor_segment_overrun(void);
  9359. void invalid_TSS(void);
  9360. void segment_not_present(void);
  9361. void stack_segment(void);
  9362. void general_protection(void);
  9363. void page_fault(void);
  9364. void coprocessor_error(void);
  9365. void reserved(void);
  9366.  
  9367. static void die(char * str,long esp_ptr,long nr)
  9368. {
  9369. long * esp = (long *) esp_ptr;
  9370. int i;
  9371.  
  9372. printk("%s: %04x\n\r",str,nr&0xffff);
  9373. printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n",
  9374. esp[1],esp[0],esp[2],esp[4],esp[3]);
  9375. printk("fs: %04x\n",_fs());
  9376. printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17));
  9377. if (esp[4] == 0x17) {
  9378. printk("Stack: ");
  9379. for (i=0;i<4;i++)
  9380. printk("%p ",get_seg_long(0x17,i+(long *)esp[3]));
  9381. printk("\n");
  9382. }
  9383. str(i);
  9384. printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i);
  9385. for(i=0;i<10;i++)
  9386. printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0])));
  9387. printk("\n\r");
  9388. do_exit(11); /* play segment exception */
  9389. }
  9390.  
  9391. void do_double_fault(long esp, long error_code)
  9392. {
  9393. die("double fault",esp,error_code);
  9394. }
  9395.  
  9396. void do_general_protection(long esp, long error_code)
  9397. {
  9398. die("general protection",esp,error_code);
  9399. }
  9400.  
  9401. void do_divide_error(long esp, long error_code)
  9402. {
  9403. die("divide error",esp,error_code);
  9404. }
  9405.  
  9406. void do_int3(long * esp, long error_code,
  9407. long fs,long es,long ds,
  9408. long ebp,long esi,long edi,
  9409. long edx,long ecx,long ebx,long eax)
  9410. {
  9411. int tr;
  9412.  
  9413. __asm__("str %%ax":"=a" (tr):"0" (0));
  9414. printk("eax\t\tebx\t\tecx\t\tedx\n\r%8x\t%8x\t%8x\t%8x\n\r",
  9415. eax,ebx,ecx,edx);
  9416. printk("esi\t\tedi\t\tebp\t\tesp\n\r%8x\t%8x\t%8x\t%8x\n\r",
  9417. esi,edi,ebp,(long) esp);
  9418. printk("\n\rds\tes\tfs\ttr\n\r%4x\t%4x\t%4x\t%4x\n\r",
  9419. ds,es,fs,tr);
  9420. printk("EIP: %8x CS: %4x EFLAGS: %8x\n\r",esp[0],esp[1],esp[2]);
  9421. }
  9422.  
  9423. void do_nmi(long esp, long error_code)
  9424. {
  9425. die("nmi",esp,error_code);
  9426. }
  9427.  
  9428. void do_debug(long esp, long error_code)
  9429. {
  9430. die("debug",esp,error_code);
  9431. }
  9432.  
  9433. void do_overflow(long esp, long error_code)
  9434. {
  9435. die("overflow",esp,error_code);
  9436. }
  9437.  
  9438. void do_bounds(long esp, long error_code)
  9439. {
  9440. die("bounds",esp,error_code);
  9441. }
  9442.  
  9443. void do_invalid_op(long esp, long error_code)
  9444. {
  9445. die("invalid operand",esp,error_code);
  9446. }
  9447.  
  9448. void do_device_not_available(long esp, long error_code)
  9449. {
  9450. die("device not available",esp,error_code);
  9451. }
  9452.  
  9453. void do_coprocessor_segment_overrun(long esp, long error_code)
  9454. {
  9455. die("coprocessor segment overrun",esp,error_code);
  9456. }
  9457.  
  9458. void do_invalid_TSS(long esp,long error_code)
  9459. {
  9460. die("invalid TSS",esp,error_code);
  9461. }
  9462.  
  9463. void do_segment_not_present(long esp,long error_code)
  9464. {
  9465. die("segment not present",esp,error_code);
  9466. }
  9467.  
  9468. void do_stack_segment(long esp,long error_code)
  9469. {
  9470. die("stack segment",esp,error_code);
  9471. }
  9472.  
  9473. void do_coprocessor_error(long esp, long error_code)
  9474. {
  9475. die("coprocessor error",esp,error_code);
  9476. }
  9477.  
  9478. void do_reserved(long esp, long error_code)
  9479. {
  9480. die("reserved (15,17-31) error",esp,error_code);
  9481. }
  9482.  
  9483. void trap_init(void)
  9484. {
  9485. int i;
  9486.  
  9487. set_trap_gate(0,&divide_error);
  9488. set_trap_gate(1,&debug);
  9489. set_trap_gate(2,&nmi);
  9490. set_system_gate(3,&int3); /* int3-5 can be called from all */
  9491. set_system_gate(4,&overflow);
  9492. set_system_gate(5,&bounds);
  9493. set_trap_gate(6,&invalid_op);
  9494. set_trap_gate(7,&device_not_available);
  9495. set_trap_gate(8,&double_fault);
  9496. set_trap_gate(9,&coprocessor_segment_overrun);
  9497. set_trap_gate(10,&invalid_TSS);
  9498. set_trap_gate(11,&segment_not_present);
  9499. set_trap_gate(12,&stack_segment);
  9500. set_trap_gate(13,&general_protection);
  9501. set_trap_gate(14,&page_fault);
  9502. set_trap_gate(15,&reserved);
  9503. set_trap_gate(16,&coprocessor_error);
  9504. for (i=17;i<32;i++)
  9505. set_trap_gate(i,&reserved);
  9506. /* __asm__("movl $0x3ff000,%%eax\n\t"
  9507. "movl %%eax,%%db0\n\t"
  9508. "movl $0x000d0303,%%eax\n\t"
  9509. "movl %%eax,%%db7"
  9510. :::"ax");*/
  9511. }
  9512.  
  9513.  
  9514. ------------------------------------------------------------------------
  9515.  
  9516. kernel/tty_io.c
  9517.  
  9518. /*
  9519. * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
  9520. * or rs-channels. It also implements echoing, cooked mode etc (well,
  9521. * not currently, but ...)
  9522. */
  9523. #include <ctype.h>
  9524. #include <errno.h>
  9525. #include <signal.h>
  9526.  
  9527. #define ALRMMASK (1<<(SIGALRM-1))
  9528.  
  9529. #include <linux/sched.h>
  9530. #include <linux/tty.h>
  9531. #include <asm/segment.h>
  9532. #include <asm/system.h>
  9533.  
  9534. #define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)
  9535. #define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
  9536. #define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)
  9537.  
  9538. #define L_CANON(tty) _L_FLAG((tty),ICANON)
  9539. #define L_ISIG(tty) _L_FLAG((tty),ISIG)
  9540. #define L_ECHO(tty) _L_FLAG((tty),ECHO)
  9541. #define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
  9542. #define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
  9543. #define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
  9544. #define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
  9545.  
  9546. #define I_UCLC(tty) _I_FLAG((tty),IUCLC)
  9547. #define I_NLCR(tty) _I_FLAG((tty),INLCR)
  9548. #define I_CRNL(tty) _I_FLAG((tty),ICRNL)
  9549. #define I_NOCR(tty) _I_FLAG((tty),IGNCR)
  9550.  
  9551. #define O_POST(tty) _O_FLAG((tty),OPOST)
  9552. #define O_NLCR(tty) _O_FLAG((tty),ONLCR)
  9553. #define O_CRNL(tty) _O_FLAG((tty),OCRNL)
  9554. #define O_NLRET(tty) _O_FLAG((tty),ONLRET)
  9555. #define O_LCUC(tty) _O_FLAG((tty),OLCUC)
  9556.  
  9557. struct tty_struct tty_table[] = {
  9558. {
  9559. {0,
  9560. OPOST|ONLCR, /* change outgoing NL to CRNL */
  9561. 0,
  9562. ICANON | ECHO | ECHOCTL | ECHOKE,
  9563. 0, /* console termio */
  9564. INIT_C_CC},
  9565. 0, /* initial pgrp */
  9566. 0, /* initial stopped */
  9567. con_write,
  9568. {0,0,0,0,""}, /* console read-queue */
  9569. {0,0,0,0,""}, /* console write-queue */
  9570. {0,0,0,0,""} /* console secondary queue */
  9571. },{
  9572. {0, /*IGNCR*/
  9573. OPOST | ONLRET, /* change outgoing NL to CR */
  9574. B2400 | CS8,
  9575. 0,
  9576. 0,
  9577. INIT_C_CC},
  9578. 0,
  9579. 0,
  9580. rs_write,
  9581. {0x3f8,0,0,0,""}, /* rs 1 */
  9582. {0x3f8,0,0,0,""},
  9583. {0,0,0,0,""}
  9584. },{
  9585. {0, /*IGNCR*/
  9586. OPOST | ONLRET, /* change outgoing NL to CR */
  9587. B2400 | CS8,
  9588. 0,
  9589. 0,
  9590. INIT_C_CC},
  9591. 0,
  9592. 0,
  9593. rs_write,
  9594. {0x2f8,0,0,0,""}, /* rs 2 */
  9595. {0x2f8,0,0,0,""},
  9596. {0,0,0,0,""}
  9597. }
  9598. };
  9599.  
  9600. /*
  9601. * these are the tables used by the machine code handlers.
  9602. * you can implement pseudo-tty's or something by changing
  9603. * them. Currently not done.
  9604. */
  9605. struct tty_queue * table_list[]={
  9606. &tty_table[0].read_q, &tty_table[0].write_q,
  9607. &tty_table[1].read_q, &tty_table[1].write_q,
  9608. &tty_table[2].read_q, &tty_table[2].write_q
  9609. };
  9610.  
  9611. void tty_init(void)
  9612. {
  9613. rs_init();
  9614. con_init();
  9615. }
  9616.  
  9617. void tty_intr(struct tty_struct * tty, int signal)
  9618. {
  9619. int i;
  9620.  
  9621. if (tty->pgrp <= 0)
  9622. return;
  9623. for (i=0;i<NR_TASKS;i++)
  9624. if (task[i] && task[i]->pgrp==tty->pgrp)
  9625. task[i]->signal |= 1<<(signal-1);
  9626. }
  9627.  
  9628. static void sleep_if_empty(struct tty_queue * queue)
  9629. {
  9630. cli();
  9631. while (!current->signal && EMPTY(*queue))
  9632. interruptible_sleep_on(&queue->proc_list);
  9633. sti();
  9634. }
  9635.  
  9636. static void sleep_if_full(struct tty_queue * queue)
  9637. {
  9638. if (!FULL(*queue))
  9639. return;
  9640. cli();
  9641. while (!current->signal && LEFT(*queue)<128)
  9642. interruptible_sleep_on(&queue->proc_list);
  9643. sti();
  9644. }
  9645.  
  9646. void copy_to_cooked(struct tty_struct * tty)
  9647. {
  9648. signed char c;
  9649.  
  9650. while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
  9651. GETCH(tty->read_q,c);
  9652. if (c==13)
  9653. if (I_CRNL(tty))
  9654. c=10;
  9655. else if (I_NOCR(tty))
  9656. continue;
  9657. else ;
  9658. else if (c==10 && I_NLCR(tty))
  9659. c=13;
  9660. if (I_UCLC(tty))
  9661. c=tolower(c);
  9662. if (L_CANON(tty)) {
  9663. if (c==ERASE_CHAR(tty)) {
  9664. if (EMPTY(tty->secondary) ||
  9665. (c=LAST(tty->secondary))==10 ||
  9666. c==EOF_CHAR(tty))
  9667. continue;
  9668. if (L_ECHO(tty)) {
  9669. if (c<32)
  9670. PUTCH(127,tty->write_q);
  9671. PUTCH(127,tty->write_q);
  9672. tty->write(tty);
  9673. }
  9674. DEC(tty->secondary.head);
  9675. continue;
  9676. }
  9677. if (c==STOP_CHAR(tty)) {
  9678. tty->stopped=1;
  9679. continue;
  9680. }
  9681. if (c==START_CHAR(tty)) {
  9682. tty->stopped=0;
  9683. continue;
  9684. }
  9685. }
  9686. if (!L_ISIG(tty)) {
  9687. if (c==INTR_CHAR(tty)) {
  9688. tty_intr(tty,SIGINT);
  9689. continue;
  9690. }
  9691. }
  9692. if (c==10 || c==EOF_CHAR(tty))
  9693. tty->secondary.data++;
  9694. if (L_ECHO(tty)) {
  9695. if (c==10) {
  9696. PUTCH(10,tty->write_q);
  9697. PUTCH(13,tty->write_q);
  9698. } else if (c<32) {
  9699. if (L_ECHOCTL(tty)) {
  9700. PUTCH('^',tty->write_q);
  9701. PUTCH(c+64,tty->write_q);
  9702. }
  9703. } else
  9704. PUTCH(c,tty->write_q);
  9705. tty->write(tty);
  9706. }
  9707. PUTCH(c,tty->secondary);
  9708. }
  9709. wake_up(&tty->secondary.proc_list);
  9710. }
  9711.  
  9712. int tty_read(unsigned channel, char * buf, int nr)
  9713. {
  9714. struct tty_struct * tty;
  9715. char c, * b=buf;
  9716. int minimum,time,flag=0;
  9717. long oldalarm;
  9718.  
  9719. if (channel>2 || nr<0) return -1;
  9720. tty = &tty_table[channel];
  9721. oldalarm = current->alarm;
  9722. time = (unsigned) 10*tty->termios.c_cc[VTIME];
  9723. minimum = (unsigned) tty->termios.c_cc[VMIN];
  9724. if (time && !minimum) {
  9725. minimum=1;
  9726. if (flag=(!oldalarm || time+jiffies<oldalarm))
  9727. current->alarm = time+jiffies;
  9728. }
  9729. if (minimum>nr)
  9730. minimum=nr;
  9731. while (nr>0) {
  9732. if (flag && (current->signal & ALRMMASK)) {
  9733. current->signal &= ~ALRMMASK;
  9734. break;
  9735. }
  9736. if (current->signal)
  9737. break;
  9738. if (EMPTY(tty->secondary) || (L_CANON(tty) &&
  9739. !tty->secondary.data && LEFT(tty->secondary)>20)) {
  9740. sleep_if_empty(&tty->secondary);
  9741. continue;
  9742. }
  9743. do {
  9744. GETCH(tty->secondary,c);
  9745. if (c==EOF_CHAR(tty) || c==10)
  9746. tty->secondary.data--;
  9747. if (c==EOF_CHAR(tty) && L_CANON(tty))
  9748. return (b-buf);
  9749. else {
  9750. put_fs_byte(c,b++);
  9751. if (!--nr)
  9752. break;
  9753. }
  9754. } while (nr>0 && !EMPTY(tty->secondary));
  9755. if (time && !L_CANON(tty))
  9756. if (flag=(!oldalarm || time+jiffies<oldalarm))
  9757. current->alarm = time+jiffies;
  9758. else
  9759. current->alarm = oldalarm;
  9760. if (L_CANON(tty)) {
  9761. if (b-buf)
  9762. break;
  9763. } else if (b-buf >= minimum)
  9764. break;
  9765. }
  9766. current->alarm = oldalarm;
  9767. if (current->signal && !(b-buf))
  9768. return -EINTR;
  9769. return (b-buf);
  9770. }
  9771.  
  9772. int tty_write(unsigned channel, char * buf, int nr)
  9773. {
  9774. static cr_flag=0;
  9775. struct tty_struct * tty;
  9776. char c, *b=buf;
  9777.  
  9778. if (channel>2 || nr<0) return -1;
  9779. tty = channel + tty_table;
  9780. while (nr>0) {
  9781. sleep_if_full(&tty->write_q);
  9782. if (current->signal)
  9783. break;
  9784. while (nr>0 && !FULL(tty->write_q)) {
  9785. c=get_fs_byte(b);
  9786. if (O_POST(tty)) {
  9787. if (c=='\r' && O_CRNL(tty))
  9788. c='\n';
  9789. else if (c=='\n' && O_NLRET(tty))
  9790. c='\r';
  9791. if (c=='\n' && !cr_flag && O_NLCR(tty)) {
  9792. cr_flag = 1;
  9793. PUTCH(13,tty->write_q);
  9794. continue;
  9795. }
  9796. if (O_LCUC(tty))
  9797. c=toupper(c);
  9798. }
  9799. b++; nr--;
  9800. cr_flag = 0;
  9801. PUTCH(c,tty->write_q);
  9802. }
  9803. tty->write(tty);
  9804. if (nr>0)
  9805. schedule();
  9806. }
  9807. return (b-buf);
  9808. }
  9809.  
  9810. /*
  9811. * Jeh, sometimes I really like the 386.
  9812. * This routine is called from an interrupt,
  9813. * and there should be absolutely no problem
  9814. * with sleeping even in an interrupt (I hope).
  9815. * Of course, if somebody proves me wrong, I'll
  9816. * hate intel for all time :-). We'll have to
  9817. * be careful and see to reinstating the interrupt
  9818. * chips before calling this, though.
  9819. */
  9820. void do_tty_interrupt(int tty)
  9821. {
  9822. copy_to_cooked(tty_table+tty);
  9823. }
  9824.  
  9825. ------------------------------------------------------------------------
  9826.  
  9827. kernel/vsprintf.c
  9828.  
  9829. /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  9830. /*
  9831. * Wirzenius wrote this portably, Torvalds fucked it up :-)
  9832. */
  9833.  
  9834. #include <stdarg.h>
  9835. #include <string.h>
  9836.  
  9837. /* we use this so that we can do without the ctype library */
  9838. #define is_digit(c) ((c) >= '0' && (c) <= '9')
  9839.  
  9840. static int skip_atoi(const char **s)
  9841. {
  9842. int i=0;
  9843.  
  9844. while (is_digit(**s))
  9845. i = i*10 + *((*s)++) - '0';
  9846. return i;
  9847. }
  9848.  
  9849. #define ZEROPAD 1 /* pad with zero */
  9850. #define SIGN 2 /* unsigned/signed long */
  9851. #define PLUS 4 /* show plus */
  9852. #define SPACE 8 /* space if plus */
  9853. #define LEFT 16 /* left justified */
  9854. #define SPECIAL 32 /* 0x */
  9855. #define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */
  9856.  
  9857. #define do_div(n,base) ({ \
  9858. int __res; \
  9859. __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \
  9860. __res; })
  9861.  
  9862. static char * number(char * str, int num, int base, int size, int precision
  9863. ,int type)
  9864. {
  9865. char c,sign,tmp[36];
  9866. const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  9867. int i;
  9868.  
  9869. if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
  9870. if (type&LEFT) type &= ~ZEROPAD;
  9871. if (base<2 || base>36)
  9872. return 0;
  9873. c = (type & ZEROPAD) ? '0' : ' ' ;
  9874. if (type&SIGN && num<0) {
  9875. sign='-';
  9876. num = -num;
  9877. } else
  9878. sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
  9879. if (sign) size--;
  9880. if (type&SPECIAL)
  9881. if (base==16) size -= 2;
  9882. else if (base==8) size--;
  9883. i=0;
  9884. if (num==0)
  9885. tmp[i++]='0';
  9886. else while (num!=0)
  9887. tmp[i++]=digits[do_div(num,base)];
  9888. if (i>precision) precision=i;
  9889. size -= precision;
  9890. if (!(type&(ZEROPAD+LEFT)))
  9891. while(size-->0)
  9892. *str++ = ' ';
  9893. if (sign)
  9894. *str++ = sign;
  9895. if (type&SPECIAL)
  9896. if (base==8)
  9897. *str++ = '0';
  9898. else if (base==16) {
  9899. *str++ = '0';
  9900. *str++ = digits[33];
  9901. }
  9902. if (!(type&LEFT))
  9903. while(size-->0)
  9904. *str++ = c;
  9905. while(i<precision--)
  9906. *str++ = '0';
  9907. while(i-->0)
  9908. *str++ = tmp[i];
  9909. while(size-->0)
  9910. *str++ = ' ';
  9911. return str;
  9912. }
  9913.  
  9914. int vsprintf(char *buf, const char *fmt, va_list args)
  9915. {
  9916. int len;
  9917. int i;
  9918. char * str;
  9919. char *s;
  9920. int *ip;
  9921.  
  9922. int flags; /* flags to number() */
  9923.  
  9924. int field_width; /* width of output field */
  9925. int precision; /* min. # of digits for integers; max
  9926. number of chars for from string */
  9927. int qualifier; /* 'h', 'l', or 'L' for integer fields */
  9928.  
  9929. for (str=buf ; *fmt ; ++fmt) {
  9930. if (*fmt != '%') {
  9931. *str++ = *fmt;
  9932. continue;
  9933. }
  9934.  
  9935. /* process flags */
  9936. flags = 0;
  9937. repeat:
  9938. ++fmt; /* this also skips first '%' */
  9939. switch (*fmt) {
  9940. case '-': flags |= LEFT; goto repeat;
  9941. case '+': flags |= PLUS; goto repeat;
  9942. case ' ': flags |= SPACE; goto repeat;
  9943. case '#': flags |= SPECIAL; goto repeat;
  9944. case '0': flags |= ZEROPAD; goto repeat;
  9945. }
  9946.  
  9947. /* get field width */
  9948. field_width = -1;
  9949. if (is_digit(*fmt))
  9950. field_width = skip_atoi(&fmt);
  9951. else if (*fmt == '*') {
  9952. /* it's the next argument */
  9953. field_width = va_arg(args, int);
  9954. if (field_width < 0) {
  9955. field_width = -field_width;
  9956. flags |= LEFT;
  9957. }
  9958. }
  9959.  
  9960. /* get the precision */
  9961. precision = -1;
  9962. if (*fmt == '.') {
  9963. ++fmt;
  9964. if (is_digit(*fmt))
  9965. precision = skip_atoi(&fmt);
  9966. else if (*fmt == '*') {
  9967. /* it's the next argument */
  9968. precision = va_arg(args, int);
  9969. }
  9970. if (precision < 0)
  9971. precision = 0;
  9972. }
  9973.  
  9974. /* get the conversion qualifier */
  9975. qualifier = -1;
  9976. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  9977. qualifier = *fmt;
  9978. ++fmt;
  9979. }
  9980.  
  9981. switch (*fmt) {
  9982. case 'c':
  9983. if (!(flags & LEFT))
  9984. while (--field_width > 0)
  9985. *str++ = ' ';
  9986. *str++ = (unsigned char) va_arg(args, int);
  9987. while (--field_width > 0)
  9988. *str++ = ' ';
  9989. break;
  9990.  
  9991. case 's':
  9992. s = va_arg(args, char *);
  9993. len = strlen(s);
  9994. if (precision < 0)
  9995. precision = len;
  9996. else if (len > precision)
  9997. len = precision;
  9998.  
  9999. if (!(flags & LEFT))
  10000. while (len < field_width--)
  10001. *str++ = ' ';
  10002. for (i = 0; i < len; ++i)
  10003. *str++ = *s++;
  10004. while (len < field_width--)
  10005. *str++ = ' ';
  10006. break;
  10007.  
  10008. case 'o':
  10009. str = number(str, va_arg(args, unsigned long), 8,
  10010. field_width, precision, flags);
  10011. break;
  10012.  
  10013. case 'p':
  10014. if (field_width == -1) {
  10015. field_width = 8;
  10016. flags |= ZEROPAD;
  10017. }
  10018. str = number(str,
  10019. (unsigned long) va_arg(args, void *), 16,
  10020. field_width, precision, flags);
  10021. break;
  10022.  
  10023. case 'x':
  10024. flags |= SMALL;
  10025. case 'X':
  10026. str = number(str, va_arg(args, unsigned long), 16,
  10027. field_width, precision, flags);
  10028. break;
  10029.  
  10030. case 'd':
  10031. case 'i':
  10032. flags |= SIGN;
  10033. case 'u':
  10034. str = number(str, va_arg(args, unsigned long), 10,
  10035. field_width, precision, flags);
  10036. break;
  10037.  
  10038. case 'n':
  10039. ip = va_arg(args, int *);
  10040. *ip = (str - buf);
  10041. break;
  10042.  
  10043. default:
  10044. if (*fmt != '%')
  10045. *str++ = '%';
  10046. if (*fmt)
  10047. *str++ = *fmt;
  10048. else
  10049. --fmt;
  10050. break;
  10051. }
  10052. }
  10053. *str = '\0';
  10054. return str-buf;
  10055. }
  10056.  
  10057. ------------------------------------------------------------------------
  10058.  
  10059. lib/close.c
  10060.  
  10061. #define __LIBRARY__
  10062. #include <unistd.h>
  10063.  
  10064. _syscall1(int,close,int,fd)
  10065.  
  10066. ------------------------------------------------------------------------
  10067.  
  10068. lib/ctype.c
  10069.  
  10070. #include <ctype.h>
  10071.  
  10072. char _ctmp;
  10073. unsigned char _ctype[] = {0x00, /* EOF */
  10074. _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
  10075. _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
  10076. _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
  10077. _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
  10078. _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
  10079. _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
  10080. _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
  10081. _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
  10082. _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
  10083. _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
  10084. _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
  10085. _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
  10086. _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
  10087. _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
  10088. _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
  10089. _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
  10090. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
  10091. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
  10092. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 160-175 */
  10093. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 176-191 */
  10094. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 192-207 */
  10095. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 208-223 */
  10096. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 224-239 */
  10097. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* 240-255 */
  10098.  
  10099.  
  10100. ------------------------------------------------------------------------
  10101.  
  10102. lib/dup.c
  10103.  
  10104. #define __LIBRARY__
  10105. #include <unistd.h>
  10106.  
  10107. _syscall1(int,dup,int,fd)
  10108.  
  10109. ------------------------------------------------------------------------
  10110.  
  10111. lib/errno.c
  10112.  
  10113. int errno;
  10114.  
  10115. ------------------------------------------------------------------------
  10116.  
  10117. lib/execve.c
  10118.  
  10119. #define __LIBRARY__
  10120. #include <unistd.h>
  10121.  
  10122. _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
  10123.  
  10124. ------------------------------------------------------------------------
  10125.  
  10126. lib/_exit.c
  10127.  
  10128. #define __LIBRARY__
  10129. #include <unistd.h>
  10130.  
  10131. volatile void _exit(int exit_code)
  10132. {
  10133. __asm__("int $0x80"::"a" (__NR_exit),"b" (exit_code));
  10134. }
  10135.  
  10136. ------------------------------------------------------------------------
  10137.  
  10138. lib/Makefile
  10139.  
  10140. #
  10141. # Makefile for some libs needed in the kernel.
  10142. #
  10143. # Note! Dependencies are done automagically by 'make dep', which also
  10144. # removes any old dependencies. DON'T put your own dependencies here
  10145. # unless it's something special (ie not a .c file).
  10146. #
  10147.  
  10148. AR =gar
  10149. AS =gas
  10150. LD =gld
  10151. LDFLAGS =-s -x
  10152. CC =gcc
  10153. CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
  10154. -finline-functions -mstring-insns -nostdinc -I../include
  10155. CPP =gcc -E -nostdinc -I../include
  10156.  
  10157. .c.s:
  10158. $(CC) $(CFLAGS) \
  10159. -S -o $*.s $<
  10160. .s.o:
  10161. $(AS) -c -o $*.o $<
  10162. .c.o:
  10163. $(CC) $(CFLAGS) \
  10164. -c -o $*.o $<
  10165.  
  10166. OBJS = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \
  10167. execve.o wait.o string.o
  10168.  
  10169. lib.a: $(OBJS)
  10170. $(AR) rcs lib.a $(OBJS)
  10171. sync
  10172.  
  10173. clean:
  10174. rm -f core *.o *.a tmp_make
  10175. for i in *.c;do rm -f `basename $$i .c`.s;done
  10176.  
  10177. dep:
  10178. sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
  10179. (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
  10180. $(CPP) -M $$i;done) >> tmp_make
  10181. cp tmp_make Makefile
  10182.  
  10183. ### Dependencies:
  10184.  
  10185. ------------------------------------------------------------------------
  10186.  
  10187. lib/open.c
  10188.  
  10189. #define __LIBRARY__
  10190. #include <unistd.h>
  10191. #include <stdarg.h>
  10192.  
  10193. int open(const char * filename, int flag, ...)
  10194. {
  10195. register int res;
  10196. va_list arg;
  10197.  
  10198. va_start(arg,flag);
  10199. __asm__("int $0x80"
  10200. :"=a" (res)
  10201. :"0" (__NR_open),"b" (filename),"c" (flag),
  10202. "d" (va_arg(arg,int)));
  10203. if (res>=0)
  10204. return res;
  10205. errno = -res;
  10206. return -1;
  10207. }
  10208.  
  10209. ------------------------------------------------------------------------
  10210.  
  10211. lib/setsid.c
  10212.  
  10213. #define __LIBRARY__
  10214. #include <unistd.h>
  10215.  
  10216. _syscall0(pid_t,setsid)
  10217.  
  10218. ------------------------------------------------------------------------
  10219.  
  10220. lib/string.c
  10221.  
  10222. #ifndef __GNUC__
  10223. #error I want gcc!
  10224. #endif
  10225.  
  10226. #define extern
  10227. #define inline
  10228. #define __LIBRARY__
  10229. #include <string.h>
  10230.  
  10231. ------------------------------------------------------------------------
  10232.  
  10233. lib/wait.c
  10234.  
  10235. #define __LIBRARY__
  10236. #include <unistd.h>
  10237. #include <sys/wait.h>
  10238.  
  10239. _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
  10240.  
  10241. pid_t wait(int * wait_stat)
  10242. {
  10243. return waitpid(-1,wait_stat,0);
  10244. }
  10245.  
  10246. ------------------------------------------------------------------------
  10247.  
  10248. lib/write.c
  10249.  
  10250. #define __LIBRARY__
  10251. #include <unistd.h>
  10252.  
  10253. _syscall3(int,write,int,fd,const char *,buf,off_t,count)
  10254.  
  10255. ------------------------------------------------------------------------
  10256.  
  10257. mm/Makefile
  10258.  
  10259. CC =gcc
  10260. CFLAGS =-O -Wall -fstrength-reduce -fcombine-regs -fomit-frame-pointer \
  10261. -finline-functions -nostdinc -I../include
  10262. AS =gas
  10263. AR =gar
  10264. LD =gld
  10265. CPP =gcc -E -nostdinc -I../include
  10266.  
  10267. .c.o:
  10268. $(CC) $(CFLAGS) \
  10269. -c -o $*.o $<
  10270. .s.o:
  10271. $(AS) -o $*.o $<
  10272. .c.s:
  10273. $(CC) $(CFLAGS) \
  10274. -S -o $*.s $<
  10275.  
  10276. OBJS = memory.o page.o
  10277.  
  10278. all: mm.o
  10279.  
  10280. mm.o: $(OBJS)
  10281. $(LD) -r -o mm.o $(OBJS)
  10282.  
  10283. clean:
  10284. rm -f core *.o *.a tmp_make
  10285. for i in *.c;do rm -f `basename $$i .c`.s;done
  10286.  
  10287. dep:
  10288. sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
  10289. (for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
  10290. cp tmp_make Makefile
  10291.  
  10292. ### Dependencies:
  10293. memory.o : memory.c ../include/signal.h ../include/sys/types.h \
  10294. ../include/linux/config.h ../include/linux/head.h ../include/linux/kernel.h \
  10295. ../include/asm/system.h
  10296.  
  10297. ------------------------------------------------------------------------
  10298.  
  10299. mm/memory.c
  10300.  
  10301. #include <signal.h>
  10302.  
  10303. #include <linux/config.h>
  10304. #include <linux/head.h>
  10305. #include <linux/kernel.h>
  10306. #include <asm/system.h>
  10307.  
  10308. int do_exit(long code);
  10309.  
  10310. #define invalidate() \
  10311. __asm__("movl %%eax,%%cr3"::"a" (0))
  10312.  
  10313. #if (BUFFER_END < 0x100000)
  10314. #define LOW_MEM 0x100000
  10315. #else
  10316. #define LOW_MEM BUFFER_END
  10317. #endif
  10318.  
  10319. /* these are not to be changed - thay are calculated from the above */
  10320. #define PAGING_MEMORY (HIGH_MEMORY - LOW_MEM)
  10321. #define PAGING_PAGES (PAGING_MEMORY/4096)
  10322. #define MAP_NR(addr) (((addr)-LOW_MEM)>>12)
  10323.  
  10324. #if (PAGING_PAGES < 10)
  10325. #error "Won't work"
  10326. #endif
  10327.  
  10328. #define copy_page(from,to) \
  10329. __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")
  10330.  
  10331. static unsigned short mem_map [ PAGING_PAGES ] = {0,};
  10332.  
  10333. /*
  10334. * Get physical address of first (actually last :-) free page, and mark it
  10335. * used. If no free pages left, return 0.
  10336. */
  10337. unsigned long get_free_page(void)
  10338. {
  10339. register unsigned long __res asm("ax");
  10340.  
  10341. __asm__("std ; repne ; scasw\n\t"
  10342. "jne 1f\n\t"
  10343. "movw $1,2(%%edi)\n\t"
  10344. "sall $12,%%ecx\n\t"
  10345. "movl %%ecx,%%edx\n\t"
  10346. "addl %2,%%edx\n\t"
  10347. "movl $1024,%%ecx\n\t"
  10348. "leal 4092(%%edx),%%edi\n\t"
  10349. "rep ; stosl\n\t"
  10350. "movl %%edx,%%eax\n"
  10351. "1:"
  10352. :"=a" (__res)
  10353. :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
  10354. "D" (mem_map+PAGING_PAGES-1)
  10355. :"di","cx","dx");
  10356. return __res;
  10357. }
  10358.  
  10359. /*
  10360. * Free a page of memory at physical address 'addr'. Used by
  10361. * 'free_page_tables()'
  10362. */
  10363. void free_page(unsigned long addr)
  10364. {
  10365. if (addr<LOW_MEM) return;
  10366. if (addr>HIGH_MEMORY)
  10367. panic("trying to free nonexistent page");
  10368. addr -= LOW_MEM;
  10369. addr >>= 12;
  10370. if (mem_map[addr]--) return;
  10371. mem_map[addr]=0;
  10372. panic("trying to free free page");
  10373. }
  10374.  
  10375. /*
  10376. * This function frees a continuos block of page tables, as needed
  10377. * by 'exit()'. As does copy_page_tables(), this handles only 4Mb blocks.
  10378. */
  10379. int free_page_tables(unsigned long from,unsigned long size)
  10380. {
  10381. unsigned long *pg_table;
  10382. unsigned long * dir, nr;
  10383.  
  10384. if (from & 0x3fffff)
  10385. panic("free_page_tables called with wrong alignment");
  10386. if (!from)
  10387. panic("Trying to free up swapper memory space");
  10388. size = (size + 0x3fffff) >> 22;
  10389. dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
  10390. for ( ; size-->0 ; dir++) {
  10391. if (!(1 & *dir))
  10392. continue;
  10393. pg_table = (unsigned long *) (0xfffff000 & *dir);
  10394. for (nr=0 ; nr<1024 ; nr++) {
  10395. if (1 & *pg_table)
  10396. free_page(0xfffff000 & *pg_table);
  10397. *pg_table = 0;
  10398. pg_table++;
  10399. }
  10400. free_page(0xfffff000 & *dir);
  10401. *dir = 0;
  10402. }
  10403. invalidate();
  10404. return 0;
  10405. }
  10406.  
  10407. /*
  10408. * Well, here is one of the most complicated functions in mm. It
  10409. * copies a range of linerar addresses by copying only the pages.
  10410. * Let's hope this is bug-free, 'cause this one I don't want to debug :-)
  10411. *
  10412. * Note! We don't copy just any chunks of memory - addresses have to
  10413. * be divisible by 4Mb (one page-directory entry), as this makes the
  10414. * function easier. It's used only by fork anyway.
  10415. *
  10416. * NOTE 2!! When from==0 we are copying kernel space for the first
  10417. * fork(). Then we DONT want to copy a full page-directory entry, as
  10418. * that would lead to some serious memory waste - we just copy the
  10419. * first 160 pages - 640kB. Even that is more than we need, but it
  10420. * doesn't take any more memory - we don't copy-on-write in the low
  10421. * 1 Mb-range, so the pages can be shared with the kernel. Thus the
  10422. * special case for nr=xxxx.
  10423. */
  10424. int copy_page_tables(unsigned long from,unsigned long to,long size)
  10425. {
  10426. unsigned long * from_page_table;
  10427. unsigned long * to_page_table;
  10428. unsigned long this_page;
  10429. unsigned long * from_dir, * to_dir;
  10430. unsigned long nr;
  10431.  
  10432. if ((from&0x3fffff) || (to&0x3fffff))
  10433. panic("copy_page_tables called with wrong alignment");
  10434. from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
  10435. to_dir = (unsigned long *) ((to>>20) & 0xffc);
  10436. size = ((unsigned) (size+0x3fffff)) >> 22;
  10437. for( ; size-->0 ; from_dir++,to_dir++) {
  10438. if (1 & *to_dir)
  10439. panic("copy_page_tables: already exist");
  10440. if (!(1 & *from_dir))
  10441. continue;
  10442. from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
  10443. if (!(to_page_table = (unsigned long *) get_free_page()))
  10444. return -1; /* Out of memory, see freeing */
  10445. *to_dir = ((unsigned long) to_page_table) | 7;
  10446. nr = (from==0)?0xA0:1024;
  10447. for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
  10448. this_page = *from_page_table;
  10449. if (!(1 & this_page))
  10450. continue;
  10451. this_page &= ~2;
  10452. *to_page_table = this_page;
  10453. if (this_page > LOW_MEM) {
  10454. *from_page_table = this_page;
  10455. this_page -= LOW_MEM;
  10456. this_page >>= 12;
  10457. mem_map[this_page]++;
  10458. }
  10459. }
  10460. }
  10461. invalidate();
  10462. return 0;
  10463. }
  10464.  
  10465. /*
  10466. * This function puts a page in memory at the wanted address.
  10467. * It returns the physical address of the page gotten, 0 if
  10468. * out of memory (either when trying to access page-table or
  10469. * page.)
  10470. */
  10471. unsigned long put_page(unsigned long page,unsigned long address)
  10472. {
  10473. unsigned long tmp, *page_table;
  10474.  
  10475. /* NOTE !!! This uses the fact that _pg_dir=0 */
  10476.  
  10477. if (page < LOW_MEM || page > HIGH_MEMORY)
  10478. printk("Trying to put page %p at %p\n",page,address);
  10479. if (mem_map[(page-LOW_MEM)>>12] != 1)
  10480. printk("mem_map disagrees with %p at %p\n",page,address);
  10481. page_table = (unsigned long *) ((address>>20) & 0xffc);
  10482. if ((*page_table)&1)
  10483. page_table = (unsigned long *) (0xfffff000 & *page_table);
  10484. else {
  10485. if (!(tmp=get_free_page()))
  10486. return 0;
  10487. *page_table = tmp|7;
  10488. page_table = (unsigned long *) tmp;
  10489. }
  10490. page_table[(address>>12) & 0x3ff] = page | 7;
  10491. return page;
  10492. }
  10493.  
  10494. void un_wp_page(unsigned long * table_entry)
  10495. {
  10496. unsigned long old_page,new_page;
  10497.  
  10498. old_page = 0xfffff000 & *table_entry;
  10499. if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {
  10500. *table_entry |= 2;
  10501. return;
  10502. }
  10503. if (!(new_page=get_free_page()))
  10504. do_exit(SIGSEGV);
  10505. if (old_page >= LOW_MEM)
  10506. mem_map[MAP_NR(old_page)]--;
  10507. *table_entry = new_page | 7;
  10508. copy_page(old_page,new_page);
  10509. }
  10510.  
  10511. /*
  10512. * This routine handles present pages, when users try to write
  10513. * to a shared page. It is done by copying the page to a new address
  10514. * and decrementing the shared-page counter for the old page.
  10515. */
  10516. void do_wp_page(unsigned long error_code,unsigned long address)
  10517. {
  10518. un_wp_page((unsigned long *)
  10519. (((address>>10) & 0xffc) + (0xfffff000 &
  10520. *((unsigned long *) ((address>>20) &0xffc)))));
  10521.  
  10522. }
  10523.  
  10524. void write_verify(unsigned long address)
  10525. {
  10526. unsigned long page;
  10527.  
  10528. if (!( (page = *((unsigned long *) ((address>>20) & 0xffc)) )&1))
  10529. return;
  10530. page &= 0xfffff000;
  10531. page += ((address>>10) & 0xffc);
  10532. if ((3 & *(unsigned long *) page) == 1) /* non-writeable, present */
  10533. un_wp_page((unsigned long *) page);
  10534. return;
  10535. }
  10536.  
  10537. void do_no_page(unsigned long error_code,unsigned long address)
  10538. {
  10539. unsigned long tmp;
  10540.  
  10541. if (tmp=get_free_page())
  10542. if (put_page(tmp,address))
  10543. return;
  10544. do_exit(SIGSEGV);
  10545. }
  10546.  
  10547. void calc_mem(void)
  10548. {
  10549. int i,j,k,free=0;
  10550. long * pg_tbl;
  10551.  
  10552. for(i=0 ; i<PAGING_PAGES ; i++)
  10553. if (!mem_map[i]) free++;
  10554. printk("%d pages free (of %d)\n\r",free,PAGING_PAGES);
  10555. for(i=2 ; i<1024 ; i++) {
  10556. if (1&pg_dir[i]) {
  10557. pg_tbl=(long *) (0xfffff000 & pg_dir[i]);
  10558. for(j=k=0 ; j<1024 ; j++)
  10559. if (pg_tbl[j]&1)
  10560. k++;
  10561. printk("Pg-dir[%d] uses %d pages\n",i,k);
  10562. }
  10563. }
  10564. }
  10565.  
  10566. ------------------------------------------------------------------------
  10567.  
  10568. mm/page.s
  10569.  
  10570. /*
  10571. * page.s contains the low-level page-exception code.
  10572. * the real work is done in mm.c
  10573. */
  10574.  
  10575. .globl _page_fault
  10576.  
  10577. _page_fault:
  10578. xchgl %eax,(%esp)
  10579. pushl %ecx
  10580. pushl %edx
  10581. push %ds
  10582. push %es
  10583. push %fs
  10584. movl $0x10,%edx
  10585. mov %dx,%ds
  10586. mov %dx,%es
  10587. mov %dx,%fs
  10588. movl %cr2,%edx
  10589. pushl %edx
  10590. pushl %eax
  10591. testl $1,%eax
  10592. jne 1f
  10593. call _do_no_page
  10594. jmp 2f
  10595. 1: call _do_wp_page
  10596. 2: addl $8,%esp
  10597. pop %fs
  10598. pop %es
  10599. pop %ds
  10600. popl %edx
  10601. popl %ecx
  10602. popl %eax
  10603. iret
  10604.  
  10605. ------------------------------------------------------------------------
  10606.  
  10607. tools/build.c
  10608.  
  10609. #include <stdio.h> /* fprintf */
  10610. #include <stdlib.h> /* contains exit */
  10611. #include <sys/types.h> /* unistd.h needs this */
  10612. #include <unistd.h> /* contains read/write */
  10613. #include <fcntl.h>
  10614.  
  10615. #define MINIX_HEADER 32
  10616. #define GCC_HEADER 1024
  10617.  
  10618. void die(char * str)
  10619. {
  10620. fprintf(stderr,"%s\n",str);
  10621. exit(1);
  10622. }
  10623.  
  10624. void usage(void)
  10625. {
  10626. die("Usage: build boot system [> image]");
  10627. }
  10628.  
  10629. int main(int argc, char ** argv)
  10630. {
  10631. int i,c,id;
  10632. char buf[1024];
  10633.  
  10634. if (argc != 3)
  10635. usage();
  10636. for (i=0;i<sizeof buf; i++) buf[i]=0;
  10637. if ((id=open(argv[1],O_RDONLY,0))<0)
  10638. die("Unable to open 'boot'");
  10639. if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
  10640. die("Unable to read header of 'boot'");
  10641. if (((long *) buf)[0]!=0x04100301)
  10642. die("Non-Minix header of 'boot'");
  10643. if (((long *) buf)[1]!=MINIX_HEADER)
  10644. die("Non-Minix header of 'boot'");
  10645. if (((long *) buf)[3]!=0)
  10646. die("Illegal data segment in 'boot'");
  10647. if (((long *) buf)[4]!=0)
  10648. die("Illegal bss in 'boot'");
  10649. if (((long *) buf)[5] != 0)
  10650. die("Non-Minix header of 'boot'");
  10651. if (((long *) buf)[7] != 0)
  10652. die("Illegal symbol table in 'boot'");
  10653. i=read(id,buf,sizeof buf);
  10654. fprintf(stderr,"Boot sector %d bytes.\n",i);
  10655. if (i>510)
  10656. die("Boot block may not exceed 510 bytes");
  10657. buf[510]=0x55;
  10658. buf[511]=0xAA;
  10659. i=write(1,buf,512);
  10660. if (i!=512)
  10661. die("Write call failed");
  10662. close (id);
  10663.  
  10664. if ((id=open(argv[2],O_RDONLY,0))<0)
  10665. die("Unable to open 'system'");
  10666. if (read(id,buf,GCC_HEADER) != GCC_HEADER)
  10667. die("Unable to read header of 'system'");
  10668. if (((long *) buf)[5] != 0)
  10669. die("Non-GCC header of 'system'");
  10670. for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
  10671. if (write(1,buf,c)!=c)
  10672. die("Write call failed");
  10673. close(id);
  10674. fprintf(stderr,"System %d bytes.\n",i);
  10675. return(0);
  10676. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement