├── README.md ├── boot.img ├── boot.s ├── build.sh ├── head.s ├── netcard_driver.s ├── pci.c ├── pci.h ├── print.h ├── sysfunc.c ├── sysfunc.h ├── tmp.s ├── tools └── wlinker.c ├── wlinker ├── wsh.c └── wvi.c /README.md: -------------------------------------------------------------------------------- 1 | Walle OS 2 | ======= 3 | by sangwf 4 | 5 | *注意* 现在的开发环境是Mac OS X,如果你是其它系统,需要根据系统环境做调整。 6 | 7 | 20130721 v1.8 release,还在进行网卡驱动的开发,MAC地址尚未成功获取。截图:http://pan.baidu.com/share/link?shareid=3243972747&uk=2667868178 8 | 9 | 20130526 v1.7 release,实现对网卡的基地址及中断号的读取。截图:http://pan.baidu.com/share/link?shareid=487871&uk=2667868178 10 | 11 | 20130126 v1.6 release,实现C语言里的字符串打印,虽然还有bug。http://pan.baidu.com/share/link?shareid=189641&uk=2667868178 12 | 13 | 20121222 walleos v1.5 release, 增加字符串打印函数。效果图:http://pan.baidu.com/share/link?shareid=147222&uk=2667868178&third=0 14 | 15 | 20121216 walleos v1.4 release,实现了获取PCI配置信息。 效果图:http://pan.baidu.com/share/link?shareid=142163&uk=2667868178 16 | 17 | 20121201 walleos v1.3 release. 效果图:http://pan.baidu.com/share/link?shareid=130839&uk=2667868178 18 | 19 | 20121009 walleos v1.2 release. 效果图:http://pan.baidu.com/share/link?shareid=80663&uk=2667868178 20 | 21 | 20121005 walleos 1.1 release. 效果图:http://pan.baidu.com/share/link?shareid=75898&uk=2667868178 22 | 23 | 20120930 walleos 1.0终于完成啦!效果图:http://pan.baidu.com/share/link?shareid=71624&uk=2667868178 24 | 25 | 20120927 目前为止的效果图:http://pan.baidu.com/share/link?shareid=69206&uk=2667868178 26 | 27 | 20120926 目前为止的效果图:http://pan.baidu.com/share/link?shareid=68635&uk=2667868178 28 | -------------------------------------------------------------------------------- /boot.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sangwf/walleos/872c9cd9e44fccba5bb93b19b22a1812ef503a26/boot.img -------------------------------------------------------------------------------- /boot.s: -------------------------------------------------------------------------------- 1 | BOOTSEG equ 0x07c0 2 | 3 | jmp BOOTSEG: go 4 | 5 | go: 6 | mov ax, cs 7 | mov ds, ax 8 | mov es, ax 9 | mov ss, ax 10 | mov sp, 0x400 11 | 12 | ready_to_load: 13 | mov bp, BootMessage ;es:bp = 串地址 14 | mov cx, 18 ;cs = 串长度 15 | mov ax, 01301h 16 | mov bx, 000ch 17 | mov dl, 0 18 | ; int 10h 19 | 20 | 21 | load_system: 22 | mov dx, 0x0000 23 | mov cx, 0x0002 24 | mov ax, 0x1000 ;SYSSEG 25 | mov es, ax 26 | xor bx, bx 27 | mov ax, 0x200 + 54 ;SYSLEN 28 | int 0x13 29 | jnc ok_load 30 | die: 31 | jmp die 32 | 33 | ok_load: 34 | cli 35 | mov ax, 0x1000 ;SYSSEG 36 | mov ds, ax 37 | xor ax, ax 38 | mov es, ax 39 | mov cx, 8192 ; 移动8192个double word(4 bytes),这里拷贝少了会导致加载的head.s代码不完整 40 | sub si, si 41 | sub di, di 42 | rep movsd 43 | 44 | mov ax, cs 45 | mov ds, ax 46 | lidt [idt_48] 47 | lgdt [gdt_48] 48 | mov eax, cr0 49 | or al, 1 50 | mov cr0, eax 51 | jmp dword 0x0008: 0x00000000 52 | 53 | gdt: 54 | dw 0 55 | dw 0 56 | dw 0 57 | dw 0 ;0x00 58 | 59 | dw 0x07FF ;0x08 60 | dw 0x0000 61 | dw 0x9A00 62 | dw 0x00C0 63 | 64 | dw 0x07FF ;0x10 65 | dw 0x0000 66 | dw 0x9200 67 | dw 0x00C0 68 | 69 | dw 0x0002 ;0x18 70 | dw 0x8000 71 | dw 0x920b 72 | dw 0x00c0 73 | 74 | dw 0x07FF ;0x20 75 | dw 0x7c00 76 | dw 0x9A00 77 | dw 0x00c0 78 | end_gdt: 79 | 80 | idt_48: 81 | dw 0 82 | dw 0, 0 83 | gdt_48: 84 | dw (end_gdt - gdt) - 1 85 | dw BOOTSEG * 16 + gdt, 0 86 | 87 | BootMessage: 88 | db "Loading System ..." 89 | 90 | times 510 - ($ - $$) db 0 91 | dw 0xAA55 92 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | if [ ! -f wlinker ]; then 2 | echo "Create a new wlinker ..." 3 | gcc -o wlinker ./tools/wlinker.c 4 | fi 5 | nasm -f bin boot.s -o boot.bin 6 | gcc -m32 -o wsh wsh.c pci.c sysfunc.c 7 | ./wlinker head.s wsh 8 | cat boot.bin system.bin > merge.bin 9 | dd conv=sync if=merge.bin of=boot.img bs=1440k count=1 10 | rm -f boot.bin head.bin system.bin merge.bin wsh 11 | -------------------------------------------------------------------------------- /head.s: -------------------------------------------------------------------------------- 1 | LATCH equ (11931800 * 2) 2 | KERNEL_SEL equ 0x08 3 | DATA_SEL equ 0x10 4 | SCRN_SEL equ 0x18 5 | LDT0_SEL equ 0x20 6 | TSS0_SEL equ 0x28 7 | LDT0_INDEX equ 4 ; GDT中第4条 8 | TSS0_INDEX equ 5 ; GDT中第5条 9 | 10 | INPUT_BUFFER_SIZE equ 1024 ; 输入缓冲区大小 11 | RETURN_KEY equ 0x1c ; return key 12 | 13 | LAST_ROW equ 24 ; 最后一行 14 | LAST_ROW_ERROR_NUM equ 30 ; 用于打印错误编号 15 | LAST_ROW_INFO equ 40 ; 用于打印错误信息 16 | LAST_ROW_TIME equ 72 ; 用于打印时间 17 | 18 | NR_SYS_FORK equ 1 ; fork系统调用编号 19 | 20 | MAX_PROCESS_COUNT equ 10 ; 最多新创建10个进程 21 | 22 | bits 32 23 | start: 24 | mov eax, DATA_SEL ;指向系统段 25 | mov ds, ax 26 | 27 | ; 这里出错的话,就检查你的数据段是不是正常的完整的拷贝到了0x0000 28 | lss esp, [init_stack] 29 | 30 | call setup_idt 31 | call setup_gdt 32 | 33 | mov eax, DATA_SEL 34 | mov ds, ax 35 | mov es, ax 36 | mov fs, ax 37 | mov gs, ax 38 | lss esp, [init_stack] 39 | 40 | mov al, 0x36 41 | mov edx, 0x43 42 | out dx, al 43 | 44 | mov eax, LATCH 45 | mov edx, 0x40 46 | out dx, al 47 | mov al, ah 48 | out dx, al 49 | 50 | mov eax, 0x00080000 51 | 52 | mov ax, int_timer 53 | mov dx, 0x8E00 54 | mov ecx, 0x08 55 | lea esi, [idt + ecx * 8] 56 | mov [esi], eax 57 | mov [4 + esi], edx 58 | 59 | ;init keyboard interrupt 60 | mov ax, int_keyboard 61 | mov dx, 0xef00 62 | mov ecx, 0x09 63 | lea esi, [idt + ecx * 8] 64 | mov [esi], eax 65 | mov [4 + esi], edx 66 | 67 | ; netcard interrupt 68 | mov ax, int_netcard 69 | mov dx, 0xef00 70 | mov ecx, 0x0B 71 | lea esi, [idt + ecx * 8] 72 | mov [esi], eax 73 | mov [4 + esi], edx 74 | 75 | 76 | ; clock interrupt: 显示时间 77 | mov ax, int_clock_display 78 | mov dx, 0xef00 79 | mov ecx, 0x79 80 | lea esi, [idt + ecx * 8] 81 | mov [esi], eax 82 | mov [4 + esi], edx 83 | 84 | ; 系统调用的统一入口 85 | mov ax, int_syscall 86 | mov dx, 0xef00 87 | mov ecx, 0x80 88 | lea esi, [idt + ecx * 8] 89 | mov [esi], eax 90 | mov [4 + esi], edx 91 | 92 | ; 中断0x81 93 | mov ax, int_print_bin 94 | mov dx, 0xef00 95 | mov ecx, 0x81 96 | lea esi, [idt + ecx * 8] 97 | mov [esi], eax 98 | mov [4 + esi], edx 99 | 100 | ; 中断0x82 101 | mov ax, int_print_hex 102 | mov dx, 0xef00 103 | mov ecx, 0x82 104 | lea esi, [idt + ecx * 8] 105 | mov [esi], eax 106 | mov [4 + esi], edx 107 | 108 | ; 中断0x83 109 | mov ax, int_print_return 110 | mov dx, 0xef00 111 | mov ecx, 0x83 112 | lea esi, [idt + ecx * 8] 113 | mov [esi], eax 114 | mov [4 + esi], edx 115 | 116 | ; 中断0x84 117 | mov ax, int_print_string 118 | mov dx, 0xef00 119 | mov ecx, 0x84 120 | lea esi, [idt + ecx * 8] 121 | mov [esi], eax 122 | mov [4 + esi], edx 123 | 124 | 125 | ; 中断0x85 126 | mov ax, int_print_hex_32 127 | mov dx, 0xef00 128 | mov ecx, 0x85 129 | lea esi, [idt + ecx * 8] 130 | mov [esi], eax 131 | mov [4 + esi], edx 132 | 133 | mov ch, 0x02 134 | mov bh, LAST_ROW 135 | mov bl, 0 ; 最左侧第0列开始 136 | lea edx, [STR_VERSION] 137 | call func_print_string_by_pos 138 | 139 | pushfd 140 | mov eax, 0xffffbfff 141 | and dword [esp], eax 142 | popfd 143 | mov eax, TSS0_SEL 144 | ltr ax 145 | mov eax, LDT0_SEL 146 | lldt ax 147 | mov dword [current], 0 148 | 149 | mov eax, 0x17 ; 设置任务0的数据段 150 | mov ds, eax 151 | 152 | sti 153 | push 0x17 ; ldt0中的第三项,表示局部数据段 154 | push usr_stk0 155 | pushfd ; EFLAGS 156 | push 0x0f ; CS, ldt0中的第二项,表示局部代码段 157 | push task0 ; IP 158 | iret 159 | 160 | setup_gdt: 161 | lgdt [lgdt_opcode] 162 | ret 163 | 164 | setup_idt: 165 | lea edx, [int_ignore] 166 | mov eax, 0x00080000 167 | mov ax, dx 168 | mov dx, 0x8E00 169 | lea edi, [idt] 170 | mov ecx, 256 171 | 172 | rp_idt: mov [edi], eax 173 | mov [edi + 4], edx 174 | add edi, 8 175 | dec ecx 176 | jne rp_idt 177 | lidt [lidt_opcode] 178 | ret 179 | 180 | write_char: 181 | push eax 182 | push ebx 183 | push ecx 184 | push edx 185 | push gs 186 | mov ebx, SCRN_SEL 187 | mov gs, bx 188 | mov bx, [scr_loc] 189 | 190 | mov dl, 0 ;作为特殊按键的标记 191 | ;处理回车按键0x1c 192 | cmp al, 0x1c 193 | jne left_ctrl_key 194 | return_key: 195 | push eax 196 | 197 | mov ax, bx 198 | mov cl, 80 199 | div cl ;al商,ah余数 200 | sub cl, ah 201 | mov dl, cl 202 | mov dh, 0 203 | add bx, dx 204 | sub bx, 1 205 | 206 | pop eax 207 | mov al, ' ' ;对于return key,直接输出一个空格 208 | left_ctrl_key: 209 | cmp al, 0x1d 210 | jne delete_key 211 | 212 | mov al, ' ' 213 | mov dl, 1 214 | delete_key: ;处理delete按键 215 | cmp al, 0x0e 216 | jne normal_char 217 | 218 | cmp bx, 0 219 | je not_delete 220 | sub bx, 1 ;减1 221 | not_delete: 222 | mov al, ' ' 223 | mov dl, 1 224 | 225 | normal_char: 226 | 227 | 228 | shl ebx, 1 229 | mov [gs: ebx],al 230 | ; color 231 | mov [gs: ebx + 1],ch 232 | 233 | shr ebx, 1 234 | 235 | ;正常的char才需要+1 236 | cmp dl, 1 237 | je not_add_loc 238 | add ebx, 1 239 | not_add_loc: 240 | call func_update_location 241 | shl ebx, 1 242 | mov [gs: ebx + 1],ch 243 | write_char_ret: 244 | pop gs 245 | pop edx 246 | pop ecx 247 | pop ebx 248 | pop eax 249 | ret 250 | 251 | ;回车换行 252 | func_write_return: 253 | push eax 254 | push ebx 255 | push ecx 256 | push edx 257 | push gs 258 | mov ebx, SCRN_SEL 259 | mov gs, bx 260 | mov bx, [scr_loc] ;bx = location 261 | 262 | mov ax, bx 263 | mov cl, 80 264 | div cl ;al商,ah余数 265 | sub cl, ah 266 | mov dl, cl 267 | mov dh, 0 268 | add bx, dx 269 | ; sub bx, 1 270 | 271 | call func_update_location 272 | pop gs 273 | pop edx 274 | pop ecx 275 | pop ebx 276 | pop eax 277 | ret 278 | 279 | 280 | ;打印dx为16进制数," 0x**** ",共占8个位置 281 | func_write_hex: 282 | push eax 283 | push ebx 284 | push ds 285 | mov eax, DATA_SEL ; 系统数据段 286 | mov ds, ax 287 | 288 | mov al, ' ' 289 | call func_write_normal_char 290 | mov al, '0' 291 | call func_write_normal_char 292 | mov al, 'x' 293 | call func_write_normal_char 294 | 295 | xor eax, 0 296 | mov al, dh 297 | shr al, 4 298 | mov al, [hex_map + eax] 299 | call func_write_normal_char 300 | xor eax, 0 301 | mov al, dh 302 | shl al, 4 303 | shr al, 4 304 | mov al, [hex_map + eax] 305 | call func_write_normal_char 306 | xor eax, 0 307 | mov al, dl 308 | shr al, 4 309 | mov al, [hex_map + eax] 310 | call func_write_normal_char 311 | xor eax, 0 312 | mov al, dl 313 | shl al, 4 314 | shr al, 4 315 | mov al, [hex_map + eax] 316 | call func_write_normal_char 317 | 318 | mov al, ' ' 319 | call func_write_normal_char 320 | pop ds 321 | pop ebx 322 | pop eax 323 | ret 324 | 325 | ;打印edx为16进制数," 0x******** ",共占12个位置 326 | func_write_hex_32: 327 | push eax 328 | push ebx 329 | push ds 330 | mov eax, DATA_SEL ; 系统数据段 331 | mov ds, ax 332 | 333 | mov al, ' ' 334 | call func_write_normal_char 335 | mov al, '0' 336 | call func_write_normal_char 337 | mov al, 'x' 338 | call func_write_normal_char 339 | 340 | ;print edx's high word 341 | push edx 342 | shr edx, 16 343 | 344 | xor eax, 0 345 | mov al, dh 346 | shr al, 4 347 | mov al, [hex_map + eax] 348 | call func_write_normal_char 349 | xor eax, 0 350 | mov al, dh 351 | shl al, 4 352 | shr al, 4 353 | mov al, [hex_map + eax] 354 | call func_write_normal_char 355 | xor eax, 0 356 | mov al, dl 357 | shr al, 4 358 | mov al, [hex_map + eax] 359 | call func_write_normal_char 360 | xor eax, 0 361 | mov al, dl 362 | shl al, 4 363 | shr al, 4 364 | mov al, [hex_map + eax] 365 | call func_write_normal_char 366 | 367 | pop edx 368 | 369 | xor eax, 0 370 | mov al, dh 371 | shr al, 4 372 | mov al, [hex_map + eax] 373 | call func_write_normal_char 374 | xor eax, 0 375 | mov al, dh 376 | shl al, 4 377 | shr al, 4 378 | mov al, [hex_map + eax] 379 | call func_write_normal_char 380 | xor eax, 0 381 | mov al, dl 382 | shr al, 4 383 | mov al, [hex_map + eax] 384 | call func_write_normal_char 385 | xor eax, 0 386 | mov al, dl 387 | shl al, 4 388 | shr al, 4 389 | mov al, [hex_map + eax] 390 | call func_write_normal_char 391 | 392 | mov al, ' ' 393 | call func_write_normal_char 394 | pop ds 395 | pop ebx 396 | pop eax 397 | ret 398 | 399 | ;打印一个常规字符al到屏幕 400 | func_write_normal_char: 401 | push eax 402 | push gs 403 | mov ebx, SCRN_SEL 404 | mov gs, bx 405 | mov bx, [scr_loc] 406 | 407 | shl ebx, 1 408 | mov [gs: ebx], al 409 | ; color 410 | mov [gs: ebx + 1], ch 411 | shr ebx, 1 412 | add ebx, 1 413 | call func_update_location 414 | pop gs 415 | pop eax 416 | ret 417 | 418 | 419 | ;更新位置偏移 420 | ;ebx为新位置请求 421 | func_update_location: 422 | cmp ebx, 1920 ;1920个字符位置 423 | jb mark_not_overflow 424 | mov ebx, 0 425 | mark_not_overflow: 426 | mov [scr_loc], ebx 427 | call func_mov_cur 428 | ret 429 | 430 | 431 | func_mov_cur: ;移动光标,ebx保存有cur要设置的位置 432 | push eax 433 | push edx 434 | 435 | ; VGA寄存器 低字节 436 | mov al, 0x0f ; 光标位置低字节索引 437 | mov dx, 0x03D4 ; 写到CRT索引寄存器 438 | out dx, al 439 | 440 | mov al, bl ; 当前位置在EBX中,BL包含低字节,BH高字节 441 | mov dx, 0x03D5 ; 写到数据寄存器 442 | out dx, al ; 低字节 443 | 444 | ; VGA 寄存器 高字节; 445 | xor eax, eax 446 | mov al, 0x0e ; 光标位置高字节索引 447 | mov dx, 0x03D4 ; 写到CRT索引寄存器 448 | out dx, al 449 | 450 | mov al, bh ; 当前位置在EBX中,BL包含低字节,BH高字节 451 | mov dx, 0x03D5 ; 写到数据寄存器 452 | out dx, al ; 高字节 453 | mov_cur_ret: 454 | pop edx 455 | pop eax 456 | ret 457 | 458 | ;输入edx所存以'\0'结尾的字符串到屏幕,ch为color 459 | func_print_string: 460 | push eax 461 | push ebx 462 | push edx 463 | 464 | mov ax, [scr_loc] 465 | mov bl, 80 466 | div bl ;al商,ah余数 467 | 468 | mov bh, al 469 | mov bl, ah 470 | call func_print_string_by_pos 471 | 472 | pop edx 473 | pop ebx 474 | pop eax 475 | ret 476 | 477 | ;输入edx所存以'\0'结尾的字符串到bh行,bl列,ch为color 478 | func_print_string_by_pos: 479 | push eax 480 | push ebx 481 | push ecx 482 | push edx 483 | 484 | .mark_wsbp_while: 485 | cmp byte [edx], 0 486 | je .mark_wsbp_ret 487 | mov cl, [edx] 488 | call func_print_char_by_pos 489 | inc bl 490 | ;处理换行问题 491 | cmp bl, 80 492 | jne .mark_wsbp_next 493 | mov bl, 0 494 | inc bh 495 | cmp bh, LAST_ROW 496 | jne .mark_wsbp_next 497 | mov bh, 0 498 | .mark_wsbp_next: 499 | inc edx 500 | jmp .mark_wsbp_while 501 | 502 | .mark_wsbp_ret: 503 | pop edx 504 | pop ecx 505 | pop ebx 506 | pop eax 507 | ret 508 | 509 | 510 | ; 输入一个字符cl到bh行,bl列,ch为color 511 | func_print_char_by_pos: 512 | push gs 513 | push eax 514 | push ebx 515 | push edx 516 | 517 | mov edx, SCRN_SEL 518 | mov gs, dx 519 | 520 | ;计算屏幕位置,bh*80+bl 521 | mov al, 80 522 | mul bh 523 | mov dx, ax 524 | 525 | mov bh, 0 526 | add dx, bx ; add bl 527 | 528 | ; print 529 | shl edx, 1 530 | mov [gs: edx], cl 531 | mov [gs: edx + 1], ch 532 | 533 | pop edx 534 | pop ebx 535 | pop eax 536 | pop gs 537 | ret 538 | 539 | ;打印一个整数ax到bh行,bl列, 颜色信息存放在ch 540 | print_binary: 541 | push gs 542 | push edx 543 | push si 544 | push di 545 | push eax 546 | 547 | ;备份 548 | mov di, ax 549 | mov edx, SCRN_SEL 550 | mov gs, dx 551 | 552 | mov si, 0 ;共16位,从左向右打印 553 | repeat_pos: 554 | mov ax, di ;还原ax 555 | 556 | mov dx, si 557 | mov cl, dl 558 | shl ax, cl 559 | shr ax, 15 ;移到最右侧1位 560 | 561 | ;计算屏幕位置,bh*80+bl+si 562 | push ax 563 | push bx 564 | 565 | mov al, 80 566 | mul bh 567 | mov dx, ax 568 | 569 | mov bh, 0 570 | add dx, bx ; add bl 571 | add dx, si ; dx存放位置 572 | 573 | pop bx 574 | pop ax 575 | 576 | ;print 577 | shl edx, 1 578 | add al, '0';加上asc偏移 579 | mov [gs: edx], al 580 | mov [gs: edx + 1], ch 581 | 582 | 583 | inc si 584 | cmp si, 16 585 | jb repeat_pos 586 | 587 | pop eax 588 | pop di 589 | pop si 590 | pop edx 591 | pop gs 592 | ret 593 | 594 | ; 打印一个整数ax到bh行,bl列, 颜色信息存放在ch 595 | ; 16进制 596 | func_print_hex_by_pos: 597 | push eax 598 | push ebx 599 | push ecx 600 | push edx 601 | push si 602 | push di 603 | push gs 604 | ;备份 605 | mov di, ax 606 | 607 | ;set gs = SCRN_SEL 608 | mov edx, SCRN_SEL 609 | mov gs, dx 610 | 611 | mov si, 0 ;共4位,从左向右打印 612 | repeat_pos2: 613 | mov ax, di ;还原ax 614 | 615 | push ax 616 | mov al, 4 617 | mul si 618 | mov cl, al 619 | pop ax 620 | 621 | shl ax, cl 622 | shr ax, 12 ;移到最右侧1位 623 | 624 | ;计算屏幕位置,bh*80+bl+si 625 | push ax 626 | push bx 627 | 628 | mov al, 80 629 | mul bh 630 | mov dx, ax 631 | 632 | mov bh, 0 633 | add dx, bx ; add bl 634 | add dx, si ; si存放偏移 635 | 636 | pop bx 637 | pop ax 638 | 639 | ;print 640 | shl edx, 1 641 | push ebx 642 | mov ebx, 0 643 | mov bl, al 644 | mov al, [hex_map + ebx] 645 | mov [gs: edx], al 646 | mov [gs: edx + 1], ch 647 | pop ebx 648 | 649 | inc si 650 | cmp si, 4 651 | jb repeat_pos2 652 | 653 | pop gs 654 | pop di 655 | pop si 656 | pop edx 657 | pop ecx 658 | pop ebx 659 | pop eax 660 | ret 661 | 662 | hex_map: 663 | db "0123456789ABCDEF" 664 | 665 | align 4 666 | int_ignore: 667 | iret ; TODO 668 | push ds 669 | push eax 670 | push ebx 671 | push edx 672 | 673 | mov eax, DATA_SEL 674 | mov ds, ax 675 | 676 | mov bh, LAST_ROW ; 行 677 | mov bl, LAST_ROW_INFO ; 列 678 | lea edx, [STR_INT_IGNORE] 679 | call func_print_string_by_pos 680 | 681 | pop edx 682 | pop ebx 683 | pop eax 684 | pop ds 685 | iret 686 | 687 | align 4 688 | func_translate_time_unit: ; 将al中的时/分/秒转换为可打印字符,放到bl/bh中 689 | push edx 690 | 691 | xor edx, edx 692 | mov dl, al 693 | shr dl, 4 694 | mov bl, [key_map + 1 + edx] 695 | 696 | xor edx, edx 697 | mov dl, al 698 | shl dl, 4 699 | shr dl, 4 700 | mov bh, [key_map + 1 + edx] 701 | 702 | pop edx 703 | ret 704 | 705 | align 4 706 | int_clock_display: ; 显示时钟 707 | push ds 708 | push eax 709 | push ebx 710 | push ecx 711 | 712 | mov eax, DATA_SEL 713 | mov ds, ax 714 | 715 | ; get time 716 | ; hour 717 | mov al, 0x04 718 | out 0x70, al 719 | in al, 0x71 720 | call func_translate_time_unit 721 | 722 | mov [STR_TIME + 0], bl 723 | mov [STR_TIME + 1], bh 724 | 725 | ; miniute 726 | mov al, 0x02 727 | out 0x70, al 728 | in al, 0x71 729 | call func_translate_time_unit 730 | 731 | mov [STR_TIME + 3], bl 732 | mov [STR_TIME + 4], bh 733 | 734 | ; second 735 | mov al, 0x00 736 | out 0x70, al 737 | in al, 0x71 738 | call func_translate_time_unit 739 | 740 | mov [STR_TIME + 6], bl 741 | mov [STR_TIME + 7], bh 742 | 743 | ; 在屏幕右下角显示时间 744 | ; 时钟颜色由2*[current]+2决定 745 | mov ch, [current] 746 | add ch, [current] 747 | add ch, 2 748 | 749 | mov bh, LAST_ROW ; 行 750 | mov bl, LAST_ROW_TIME ; 列 751 | lea edx, [STR_TIME] 752 | call func_print_string_by_pos 753 | 754 | pop ecx 755 | pop ebx 756 | pop eax 757 | pop ds 758 | iret 759 | 760 | mode: db 0 761 | leds: db 0 762 | e0: db 0 763 | 764 | align 4 765 | int_keyboard: 766 | push eax 767 | push ebx 768 | push ecx 769 | push edx 770 | push ds 771 | push es 772 | 773 | mov eax, 0x10 ; 系统数据段 774 | mov ds, ax 775 | mov es, ax 776 | 777 | in al, 0x60 778 | 779 | 780 | cmp al, 0xe0 781 | je set_e0 782 | cmp al, 0xe1 783 | je set_e1 784 | 785 | call do_self 786 | 787 | mov cl, 0 788 | mov [e0], cl 789 | 790 | e0_e1: 791 | in al, 0x61 792 | or al, 0x80 ; al 位7置位,禁止键盘工作 793 | out 0x61, al ;使PPI PB7位置位 794 | add al, 0x7F ; al位7复位 795 | out 0x61, al ; 使PPI PB7位复位,允许键盘工作 796 | mov al, 0x20 ;向8259中断芯片发送EOI中断结束信号 797 | out 0x20, al 798 | 799 | kb_ret: 800 | pop es 801 | pop ds 802 | pop edx 803 | pop ecx 804 | pop ebx 805 | pop eax 806 | iret 807 | 808 | set_e0: 809 | mov cl, 1 810 | mov [e0],cl 811 | jmp e0_e1 812 | set_e1: 813 | mov cl, 2 814 | mov [e0],cl 815 | jmp e0_e1 816 | 817 | do_self: 818 | ;剔除按键弹起的消息,第8位为1 819 | mov bl, al 820 | and bl, 0x80 821 | cmp bl, 0 822 | jne none 823 | 824 | ; 在屏幕最下方输出按键的二进制码,用于调试 825 | mov ch, 0x07 ; screen color 826 | mov bh, LAST_ROW 827 | mov bl, 30 828 | call print_binary 829 | 830 | and ax, 0x007f 831 | mov al, [key_map + eax] 832 | 833 | ; 记录到buffer中 834 | push edx 835 | mov edx, [input_position] 836 | mov [input_buffer + edx], al 837 | 838 | ; update input position 839 | inc edx 840 | cmp edx, INPUT_BUFFER_SIZE 841 | jb .mark_not_update_input_position 842 | mov edx, 0 843 | .mark_not_update_input_position: 844 | mov [input_position], edx 845 | 846 | ; 在屏幕上输出字符 847 | call write_char 848 | 849 | pop edx 850 | none: 851 | ret 852 | 853 | ; for macbook pro keyboard 854 | key_map: 855 | db 0 856 | db "01234567890-=" 857 | db 0x0e ; delete key 858 | db " qwertyuiop[]" 859 | db RETURN_KEY ; return key 860 | db 0x1d ; ctrl key(left) 861 | db "asdfghjkl;'" 862 | db " \zxcvbnm,./" 863 | 864 | times 128 db 0 865 | 866 | ; 用于按键输入的buffer,循环队列,1024个字节 867 | input_buffer: 868 | times INPUT_BUFFER_SIZE db 0 869 | ; 表示当前buffer的下一个可输入字符 870 | input_position: 871 | dd 0 872 | ; 表示Shell当前处理到的字符位置 873 | deal_position: 874 | dd 0 875 | 876 | 877 | align 4 878 | int_timer: 879 | push ds 880 | push eax 881 | push ebx 882 | 883 | mov eax, DATA_SEL 884 | mov ds, ax 885 | 886 | mov al, 0x20 887 | out 0x20, al 888 | jmp timer_ret ; TODO 889 | 890 | mov ebx, [process_count] 891 | inc ebx ; process_count + 1 892 | mov eax, [current] 893 | inc eax ; next task 894 | 895 | 896 | cmp eax, ebx 897 | jne task_switch 898 | mov eax, 0 899 | cmp eax, [current] 900 | je timer_ret ; 处理只有0号进程的情况,不进行切换 901 | task_switch: 902 | mov [current], eax 903 | add eax, TSS0_INDEX ; 加上偏移 904 | shl eax, 3 905 | push eax 906 | push 0 907 | jmp far [esp + 0] 908 | add esp, 4 909 | 910 | timer_ret: 911 | pop ebx 912 | pop eax 913 | pop ds 914 | iret 915 | 916 | align 4 917 | int_netcard: 918 | push ds 919 | push edx 920 | push ecx 921 | push ebx 922 | push eax 923 | mov ch, 0x02 924 | mov bh, LAST_ROW 925 | mov bl, 0 926 | lea edx, [STR_VERSION] 927 | call func_print_string_by_pos 928 | pop eax 929 | pop ebx 930 | pop ecx 931 | pop edx 932 | pop ds 933 | iret 934 | 935 | align 4 936 | ; fork系统调用的实现 937 | ; @input eax = NR_SYS_FORK 938 | ; @return 父进程的用户栈压入process_count,子进程的用户栈压入0 939 | func_syscall_fork: 940 | ; 判断是否到最大值 941 | push edx 942 | push ecx 943 | push ebx 944 | push eax 945 | 946 | ; TODO 现在并没有实现保存现有process的寄存器状态,也就是tss中的数据是过时的 947 | ; 对于子进程,等于复制的是过时的tss,需要处理 948 | 949 | mov edx, [process_count] 950 | cmp edx, MAX_PROCESS_COUNT 951 | jne .mark_copy_process 952 | pop eax 953 | pop ebx 954 | pop ecx 955 | pop edx 956 | ret 957 | 958 | .mark_copy_process: 959 | ; process_count++ 960 | inc edx 961 | mov [process_count], edx 962 | ; 复制gdt中一项 963 | mov ecx, [current] 964 | mov ebx, [gdt_new_process_base + ecx * 8] 965 | mov [gdt_new_process_base + edx * 8], ebx 966 | mov ebx, [gdt_new_process_base + ecx * 8 + 4] 967 | mov [gdt_new_process_base + edx * 8 + 4], ebx 968 | 969 | ; 更新gdt新条目中,tss的值 970 | lea ebx, [tss_start + edx * 8] 971 | mov [gdt_new_process_base + edx * 8 + 2], ebx 972 | 973 | ; 复制tss段, 需要改写进程内核栈和用户栈,并复制两个栈里的内容 974 | .mark_copy_tss_loop: 975 | mov ebx, 0 976 | push eax 977 | push ebx 978 | push ecx 979 | push edx 980 | 981 | mov ax, 104 982 | mul cx 983 | mov ebx, eax 984 | mov ax, 4 985 | mul bx 986 | add ebx, eax 987 | mov ecx, [tss_start + ebx] 988 | 989 | mov ax, 104 990 | mul dx 991 | mov ebx, eax 992 | mov ax, 4 993 | mul bx 994 | add ebx, eax 995 | mov [tss_start + ebx], ecx 996 | 997 | pop edx 998 | pop ecx 999 | pop ebx 1000 | pop eax 1001 | inc ebx 1002 | cmp ebx, 26 1003 | je .mark_copy_tss_finish 1004 | jmp .mark_copy_tss_loop 1005 | .mark_copy_tss_finish: 1006 | ; 更新tss中的内核栈和用户栈 1007 | ; 内核栈是第1个dd,就是减去一个两内核栈地址的偏移 1008 | mov eax, edx 1009 | sub eax, ecx 1010 | mov bx, 128 * 4 1011 | mul bx 1012 | 1013 | ; tss_start + edx * 104 + 4 1014 | push eax 1015 | mov eax, edx 1016 | mov bx, 104 1017 | mul bx 1018 | lea ebx, [tss_start] 1019 | add ebx, eax 1020 | add ebx, 4 1021 | pop eax 1022 | 1023 | sub [ebx], eax 1024 | ; 用户栈是第14个dd,减去两用户栈的偏移,与两内核栈偏移相等 1025 | add ebx, 52 ; 4 * 13 1026 | sub [ebx], eax 1027 | 1028 | ; 复制两个栈里的内容,每个栈的大小为128 * 4 = 512B 1029 | mov eax, ds 1030 | mov es, eax 1031 | lea si, [user_kernel_stack_head] 1032 | mov eax, ecx 1033 | add eax, 1 1034 | mov bx, 512 1035 | mul bx 1036 | sub si, ax 1037 | 1038 | lea di, [user_kernel_stack_head] 1039 | mov eax, edx 1040 | add eax, 1 1041 | mul bx 1042 | sub di, ax 1043 | 1044 | push ecx 1045 | mov ecx, 512 1046 | rep movsb 1047 | pop ecx 1048 | 1049 | lea si, [user_stack_head] 1050 | mov eax, ecx 1051 | add eax, 1 1052 | mul bx 1053 | sub si, ax 1054 | 1055 | lea di, [user_stack_head] 1056 | mov eax, edx 1057 | add eax, 1 1058 | mul bx 1059 | sub di, ax 1060 | 1061 | push ecx 1062 | mov ecx, 512 1063 | rep movsb 1064 | pop ecx 1065 | 1066 | 1067 | ; 给父进程的用户栈压入process_count,给子进程的用户栈压入0 1068 | ; ebp为用户栈esp的地址,这里在esp - 4的位置,压入返回值 1069 | push edx 1070 | lea ebx, [tss_start] 1071 | mov eax, ecx 1072 | mov dx, 104 1073 | mul dx 1074 | add ebx, eax 1075 | add ebx, 4 1076 | 1077 | mov [ebx], ebp 1078 | pop edx 1079 | mov [ebp - 4], edx ; edx is process_count 1080 | 1081 | push ecx 1082 | lea ebx, [tss_start] 1083 | mov eax, edx 1084 | mov cx, 104 1085 | mul cx 1086 | add ebx, eax 1087 | add ebx, 4 1088 | 1089 | mov [ebx], ebp 1090 | mov dword [ebp - 4], 0 ; 0 to sub process 1091 | pop ecx 1092 | 1093 | .mark_syscall_fork_ret: 1094 | pop eax 1095 | pop ebx 1096 | pop ecx 1097 | pop edx 1098 | ret 1099 | 1100 | align 4 1101 | int_syscall: 1102 | push ebp 1103 | ; ebp用于存放到用户栈的esp值,这里要分清楚用户栈和内核栈 1104 | ; 当进行中断时,系统会依次在内核栈中压入ss0, esp0, eflags, cs, eip 1105 | mov ebp, [esp + 16] ; 在esp0之上,还存放了eflags, cs, eip, ebp 1106 | push ds 1107 | push edx 1108 | push ecx 1109 | push ebx 1110 | 1111 | mov ebx, DATA_SEL 1112 | mov ds, bx 1113 | 1114 | ; 打印准备 1115 | mov ch, 0x02 1116 | mov bh, LAST_ROW 1117 | 1118 | ; 打印系统调用编号ax 1119 | mov bl, LAST_ROW_ERROR_NUM 1120 | call func_print_hex_by_pos 1121 | 1122 | 1123 | cmp eax, NR_SYS_FORK 1124 | je .mark_fork 1125 | jmp .mark_syscall_error 1126 | 1127 | .mark_fork: 1128 | ; 打印fork说明 1129 | mov bl, LAST_ROW_INFO 1130 | lea edx, [STR_FORK_SYSCALL] 1131 | call func_print_string_by_pos 1132 | 1133 | ; call func_syscall_fork 1134 | 1135 | mov bl, LAST_ROW_INFO 1136 | lea edx, [STR_FORK_SYSCALL_DONE] 1137 | call func_print_string_by_pos 1138 | 1139 | 1140 | jmp .mark_syscall_ret 1141 | 1142 | .mark_syscall_error: 1143 | ; 打印出错信息 1144 | mov bl, LAST_ROW_INFO 1145 | lea edx, [STR_INVALID_SYSCALL] 1146 | call func_print_string_by_pos 1147 | 1148 | .mark_syscall_ret: 1149 | pop ebx 1150 | pop ecx 1151 | pop edx 1152 | pop ds 1153 | pop ebp 1154 | iret 1155 | 1156 | align 4 1157 | int_print_bin: 1158 | push ds 1159 | push edx 1160 | push ecx 1161 | push ebx 1162 | push eax 1163 | mov ch, 0x02; color 1164 | call print_binary 1165 | pop eax 1166 | pop ebx 1167 | pop ecx 1168 | pop edx 1169 | pop ds 1170 | iret 1171 | 1172 | align 4 1173 | int_print_hex: 1174 | push ds 1175 | push edx 1176 | push ecx 1177 | push ebx 1178 | push eax 1179 | ;print dx 1180 | call func_write_hex 1181 | pop eax 1182 | pop ebx 1183 | pop ecx 1184 | pop edx 1185 | pop ds 1186 | iret 1187 | 1188 | align 4 1189 | int_print_hex_32: 1190 | push ds 1191 | push edx 1192 | push ecx 1193 | push ebx 1194 | push eax 1195 | ;print dx 1196 | call func_write_hex_32 1197 | pop eax 1198 | pop ebx 1199 | pop ecx 1200 | pop edx 1201 | pop ds 1202 | iret 1203 | 1204 | 1205 | align 4 1206 | int_print_return: 1207 | call func_write_return 1208 | iret 1209 | 1210 | align 4 1211 | int_print_string: 1212 | mov ch, 0x02 ;color 1213 | call func_print_string 1214 | iret 1215 | 1216 | STR_VERSION: 1217 | db "WALLEOS V2.0(2013/10/23): " 1218 | db 0 1219 | STR_INVALID_SYSCALL: 1220 | db "System Call Invalid! " 1221 | db 0 1222 | STR_FORK_SYSCALL: 1223 | db "System Call ! " 1224 | db 0 1225 | 1226 | STR_FORK_SYSCALL_DONE: 1227 | db "System Call Done! " 1228 | db 0 1229 | 1230 | 1231 | STR_TIME: 1232 | db 0, 0, ':', 0, 0 , ':', 0, 0 1233 | db 0 1234 | STR_INT_IGNORE: 1235 | db "Ignore Interrupt! " 1236 | db 0 1237 | 1238 | process_count: ; 目前已使用的进程数 1239 | dd 0 1240 | current: 1241 | dd 0 1242 | scr_loc: 1243 | dd 0 1244 | 1245 | align 4 1246 | dw 0 1247 | lidt_opcode: 1248 | dw 256 * 8 - 1 1249 | dd idt 1250 | lgdt_opcode: 1251 | dw (end_gdt - gdt) - 1 1252 | dw gdt, 0 1253 | 1254 | align 8 1255 | idt: 1256 | times 2048 db 0 1257 | 1258 | gdt: 1259 | dw 0, 0, 0, 0 1260 | dw 0x07ff, 0x0000, 0x9a00, 0x00c0 ; 1, 0x08 1261 | dw 0x07ff, 0x0000, 0x9200, 0x00c0 ; 2, 0x10 1262 | dw 0x0002, 0x8000, 0x920b, 0x00c0 ; 3, 0x18 1263 | dw 0x40, ldt0, 0xe200, 0x0 ; 4 = LDT0_INDEX , 0x20 1264 | gdt_new_process_base: 1265 | dw 0x68, tss0, 0xe900, 0x0 ; 5 = TSS0_INDEX , 0x28 1266 | times 4 * MAX_PROCESS_COUNT dw 0 ; 从第8个开始,提供额外10个进程空间 1267 | end_gdt: 1268 | times 128 dd 0 1269 | init_stack: 1270 | dd init_stack 1271 | dw 0x10 1272 | 1273 | align 8 1274 | ldt0: dw 0, 0, 0, 0 1275 | dw 0x03ff, 0x0000, 0xfa00, 0x00c0 1276 | dw 0x03ff, 0x0000, 0xf200, 0x00c0 1277 | align 8 1278 | tss_start: ; 存放新分配的tss空间 1279 | tss0: dd 0 1280 | dd krn_stk0, 0x10 ; 第1个dd是内核栈 1281 | dd 0, 0, 0, 0, 0 1282 | dd 0, 0, 0, 0, 0 1283 | dd 0 1284 | dd 0, 0, 0, 0 ; 第14个dd是用户栈 1285 | dd 0, 0, 0, 0x17, 0, 0 1286 | dd LDT0_SEL, 0x80000000 1287 | 1288 | times 26 * MAX_PROCESS_COUNT dd 0 ; 用于存放新进程的tss 1289 | 1290 | task0: 1291 | push eax 1292 | push ebx 1293 | push ecx 1294 | 1295 | mov ecx, 1 ; 创建5个子进程 1296 | .mark_create_sub_task: 1297 | mov eax, NR_SYS_FORK ; fork 1298 | int 0x80 1299 | hlt 1300 | mov ebx, [esp - 4] ; 取出返回值 1301 | cmp ebx, 0 ; 判断是否为子进程 1302 | 1303 | jne .mark_deal_sub_task 1304 | dec ecx 1305 | cmp ecx, 0 1306 | je .mark_finish 1307 | jmp .mark_create_sub_task 1308 | .mark_deal_sub_task: 1309 | int 0x79 ; 显示时钟,时钟颜色由当前进程号决定 1310 | jmp .mark_deal_sub_task 1311 | .mark_finish: 1312 | pop ecx 1313 | pop ebx 1314 | pop eax 1315 | jmp task0 1316 | 1317 | times 128 * MAX_PROCESS_COUNT dd 0 1318 | times 128 dd 0 1319 | usr_stk0: 1320 | user_stack_head: 1321 | 1322 | times 128 * MAX_PROCESS_COUNT dd 0 1323 | times 128 dd 0 1324 | krn_stk0: 1325 | user_kernel_stack_head: 1326 | -------------------------------------------------------------------------------- /netcard_driver.s: -------------------------------------------------------------------------------- 1 | RTL8139_REG_COMMAND equ 0x37 2 | RTL8139_REG_TXCONFIG_2 equ 0x42 ; transmit configuration register 2 3 | RTL8139_REG_RXCONFIG equ 0x44 ; receive configuration register 0 4 | RTL8139_REG_9346CR equ 0x50 ; serial eeprom 93C46 command register 5 | RTL8139_REG_CONFIG1 equ 0x52 ; configuration register 1 6 | RTL8139_REG_CONFIG4 equ 0x5a ; configuration register 4 7 | RTL8139_REG_HLTCLK equ 0x5b ; undocumented halt clock register 8 | 9 | RTL8139_BIT_LWACT equ 4 ; see RTL8139_REG_CONFIG1 10 | RTL8139_BIT_PMEn equ 0 ; power management enabled 11 | RTL8139_BIT_LWPTN equ 2 ; see RTL8139_REG_CONFIG4 12 | 13 | NC_IO_ADDR equ 0xD8820004 ; netcard io address 14 | 15 | RTL8139_BIT_93C46_EEM1 equ 7 ; RTL8139 eeprom operating mode1 16 | RTL8139_BIT_93C46_EEM0 equ 6 ; RTL8139 eeprom operating mode0 17 | 18 | EE_93C46_REG_ETH_ID equ 7 ; MAC offset 19 | EE_93C56_READ_CMD equ 11000000000b ; 110b + 8bit address 20 | EE_93C56_CMD_LENGTH equ 11 ; start bit + cmd + 8bit address 21 | 22 | VER_RTL8139 equ 1100000b 23 | VER_RTL8139A equ 1110000b 24 | VER_RTL8139B equ 1111000b 25 | VER_RTL8130 equ VER_RTL8139B 26 | VER_RTL8139C equ 1110100b 27 | VER_RTL8100 equ 1111010b 28 | VER_RTL8100B equ 1110101b 29 | VER_RTL8139D equ VER_RTL8100B 30 | VER_RTL8139CP equ 1110110b 31 | VER_RTL8101 equ 1110111b 32 | 33 | align 4 34 | hw_ver_array: db VER_RTL8139, VER_RTL8139A, VER_RTL8139B, VER_RTL8139C 35 | db VER_RTL8100, VER_RTL8139D, VER_RTL8139CP, VER_RTL8101 36 | HW_VER_ARRAY_SIZE equ 8 37 | 38 | mac_addr: db 0, 0, 0, 0, 0, 0 39 | 40 | func_nc_probe: 41 | mov edx, NC_IO_ADDR 42 | add edx, RTL8139_REG_HLTCLK 43 | mov al, 'R' 44 | out dx, al 45 | 46 | add edx, RTL8139_REG_9346CR - RTL8139_REG_HLTCLK 47 | mov al, 1 48 | shl al, RTL8139_BIT_93C46_EEM1 49 | mov ah, 1 50 | shl ah, RTL8139_BIT_93C46_EEM0 51 | or al, ah 52 | out dx, al 53 | 54 | add edx, RTL8139_REG_CONFIG1 - RTL8139_REG_9346CR 55 | in al, dx 56 | 57 | mov ah, 1 58 | shl ah, RTL8139_BIT_PMEn 59 | or al, ah 60 | mov ah, 1 61 | shl ah, RTL8139_BIT_LWACT 62 | not ah 63 | and al, ah 64 | out dx, al 65 | add edx, RTL8139_REG_CONFIG4 - RTL8139_REG_CONFIG1 66 | in al, dx 67 | 68 | mov ah, 1 69 | shl ah, RTL8139_BIT_LWPTN 70 | not ah 71 | and al, ah 72 | out dx, al 73 | 74 | xor al, al 75 | mov edx, NC_IO_ADDR 76 | add edx, RTL8139_REG_9346CR 77 | out dx, al 78 | 79 | ret 80 | 81 | func_nc_reset: 82 | mov edx, NC_IO_ADDR 83 | add edx, RTL8139_REG_COMMAND 84 | in al, dx 85 | ; get MAC address 86 | mov ecx, 2 87 | .mac_read_loop: 88 | lea eax, [EE_93C46_REG_ETH_ID + ecx] 89 | push ecx 90 | call func_eeprom_read 91 | pop ecx 92 | mov [mac_addr + ecx * 2], ax 93 | 94 | 95 | dec ecx 96 | jns .mac_read_loop 97 | 98 | ret 99 | 100 | ; @input al 101 | ; @output ax 102 | ; suppose 93c56 type 103 | func_eeprom_read: 104 | movzx ebx, al 105 | or bx, EE_93C56_READ_CMD 106 | mov cx, EE_93C56_CMD_LENGTH - 1 107 | 108 | mov edx, NC_IO_ADDR + RTL8139_REG_9346CR ; edx = command register address 109 | 110 | mov al, 10001000b ; wake up eeprom 111 | out dx, al 112 | 113 | .cmd_loop: 114 | mov al, 10001000b 115 | bt bx, cx 116 | jnc .zero_bit 117 | or al, 00000010b 118 | .zero_bit: 119 | out dx, al 120 | or al, 00000100b 121 | out dx, al 122 | dec cx 123 | jns .cmd_loop 124 | 125 | mov al, 10001000b 126 | out dx, al 127 | mov cl, 0xf 128 | .read_loop: 129 | shl ebx, 1 130 | mov al, 10001100b 131 | out dx, al 132 | in al, dx 133 | and al, 00000001b 134 | jz .dont_set 135 | inc ebx 136 | .dont_set: 137 | mov al, 10001000b 138 | out dx, al 139 | dec cl 140 | jns .read_loop 141 | xor al, al 142 | out dx, al 143 | mov ax, bx 144 | 145 | 146 | ; for test 147 | ret 148 | mov edx, NC_IO_ADDR + RTL8139_REG_RXCONFIG 149 | in al, dx 150 | push ecx 151 | push ebx 152 | push eax 153 | mov ch, 0x03 154 | add cl, 10 155 | mov bh, cl 156 | mov bl, 0 157 | int 0x81 158 | pop eax 159 | pop ebx 160 | pop ecx 161 | 162 | ret 163 | -------------------------------------------------------------------------------- /pci.c: -------------------------------------------------------------------------------- 1 | // (C) 2013 Wenfeng Sang 2 | 3 | #include "print.h" 4 | 5 | #define ind(port) ({ \ 6 | unsigned long _v; \ 7 | __asm__ volatile ("in %%dx, %%eax":"=a" (_v):"d" (port)); \ 8 | _v; \ 9 | }) 10 | 11 | #define outd(port, value) ({ \ 12 | __asm__ volatile ("out %%eax, %%dx"::"d" (port), "a" (value) ); \ 13 | }) 14 | 15 | #define hlt() ({ \ 16 | __asm__ volatile ("hlt"::); \ 17 | }) 18 | 19 | 20 | 21 | #define PCI_CONFIG_READ_WORD(lbus, lslot, lfunc, offset, address, value) \ 22 | ({ \ 23 | address = (unsigned long)((lbus << 16) | (lslot << 11) | \ 24 | (lfunc << 8) | (offset & 0xfc) | ((unsigned int)0x80000000)); \ 25 | outd(0xCF8, address); \ 26 | value = (unsigned short)((ind(0xCFC) >> ((offset & 2) * 8)) & 0xffff); \ 27 | }) 28 | 29 | #define PCI_CONFIG_READ_DWORD(lbus, lslot, lfunc, offset, address, value) \ 30 | ({ \ 31 | address = (unsigned long)((lbus << 16) | (lslot << 11) | \ 32 | (lfunc << 8) | (offset & 0xfc) | ((unsigned int)0x80000000)); \ 33 | outd(0xCF8, address); \ 34 | value = ind(0xCFC); \ 35 | }) 36 | 37 | #define PCI_CONFIG_WRITE_DWORD(lbus, lslot, lfunc, offset, address, value) \ 38 | ({ \ 39 | address = (unsigned long)((lbus << 16) | (lslot << 11) | \ 40 | (lfunc << 8) | (offset & 0xfc) | ((unsigned int)0x80000000)); \ 41 | outd(0xCF8, address); \ 42 | outd(0xCFC, value); \ 43 | }) 44 | 45 | 46 | /* 47 | func: get a valid device 48 | */ 49 | unsigned short getOneValidDevice(void) 50 | { 51 | unsigned long lbus; 52 | unsigned long lslot; 53 | unsigned long lfunc = 0; 54 | unsigned short device; 55 | unsigned short vendor; 56 | unsigned long address; 57 | unsigned short class_sub; 58 | unsigned short progif_rev; 59 | unsigned short pin_line; 60 | unsigned long base_address; 61 | unsigned short cmd; 62 | unsigned short status; 63 | 64 | print_string(" VENDOR DEVICE CMD STATUS CLASS|SUB PROGIF|REV PIN|LINE BASE_ADDR"); 65 | print_return(); 66 | 67 | for (lbus =0; lbus < 256; lbus++) { 68 | for (lslot = 0; lslot < 32; lslot++) { 69 | for (lfunc = 0; lfunc < 8; lfunc++) { 70 | PCI_CONFIG_READ_WORD(lbus, lslot, lfunc, 0x00, address, vendor); 71 | /*vendor = pciConfigReadWord(bus, slot, 0, 0);*/ 72 | if(vendor != 0xFFFF) { 73 | /* device = pciConfigReadWord(bus, slot, 0, 2); */ 74 | PCI_CONFIG_READ_WORD(lbus, lslot, lfunc, 0x02, address, device); 75 | /* Class code|subclass */ 76 | PCI_CONFIG_READ_WORD(lbus, lslot, lfunc, 0x0a, address, class_sub); 77 | /* Command */ 78 | PCI_CONFIG_READ_WORD(lbus, lslot, lfunc, 0x04, address, cmd); 79 | /* Status */ 80 | PCI_CONFIG_READ_WORD(lbus, lslot, lfunc, 0x06, address, status); 81 | /* Prog IF| Revision ID */ 82 | PCI_CONFIG_READ_WORD(lbus, lslot, lfunc, 0x08, address, progif_rev); 83 | /* Interrupt PIN | Interrupt Line */ 84 | PCI_CONFIG_READ_WORD(lbus, lslot, lfunc, 0x3c, address, pin_line); 85 | /* base address #0 */ 86 | PCI_CONFIG_READ_DWORD(lbus, lslot, lfunc, 0x10, address, base_address); 87 | 88 | // netcard: intel e1000 89 | if ((vendor == 0x8086) && (device == 0x100F)) { 90 | print_short(vendor); 91 | print_short(device); 92 | print_short(cmd); 93 | print_short(status); 94 | print_short(class_sub); 95 | print_short(progif_rev); 96 | print_short(pin_line); 97 | print_long(base_address & 0xFFFFFFFC); 98 | print_return(); 99 | } 100 | } 101 | } 102 | } 103 | } 104 | 105 | // print_string(" Today is 20130526, I'm coding for NetCard."); 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /pci.h: -------------------------------------------------------------------------------- 1 | unsigned short getOneValidDevice(void); 2 | -------------------------------------------------------------------------------- /print.h: -------------------------------------------------------------------------------- 1 | #ifndef _PRINT_H 2 | #define _PRINT_H 3 | 4 | #define print_short(value) ({ \ 5 | __asm__ volatile ("int $0x82"::"d" (value) ); \ 6 | }) 7 | 8 | #define print_long(value) ({ \ 9 | __asm__ volatile ("int $0x85"::"d" (value) ); \ 10 | }) 11 | 12 | 13 | #define print_string(address) ({ \ 14 | __asm__ volatile ("int $0x84"::"d" (address) ); \ 15 | }) 16 | 17 | 18 | #define print_return() ({ \ 19 | __asm__ volatile ("int $0x83"::); \ 20 | }) 21 | 22 | #endif // _PRINT_H 23 | 24 | 25 | -------------------------------------------------------------------------------- /sysfunc.c: -------------------------------------------------------------------------------- 1 | void *memcpy(void *dest, const void *src, unsigned int count) 2 | { 3 | char *tmp = dest; 4 | const char *s = src; 5 | while (count--) 6 | *tmp = *s ; 7 | return dest; 8 | } 9 | -------------------------------------------------------------------------------- /sysfunc.h: -------------------------------------------------------------------------------- 1 | void *memcpy(void *dest, const void *src, unsigned int count); 2 | -------------------------------------------------------------------------------- /tmp.s: -------------------------------------------------------------------------------- 1 | main: 2 | (__TEXT,__text) section 3 | start: 4 | 00001c40 pushl $0x00 5 | 00001c42 movl %esp,%ebp 6 | 00001c44 andl $0xf0,%esp 7 | 00001c47 subl $0x10,%esp 8 | 00001c4a movl 0x04(%ebp),%ebx 9 | 00001c4d movl %ebx,(%esp) 10 | 00001c50 leal 0x08(%ebp),%ecx 11 | 00001c53 movl %ecx,0x04(%esp) 12 | 00001c57 addl $0x01,%ebx 13 | 00001c5a shll $0x02,%ebx 14 | 00001c5d addl %ecx,%ebx 15 | 00001c5f movl %ebx,0x08(%esp) 16 | 00001c63 movl (%ebx),%eax 17 | 00001c65 addl $0x04,%ebx 18 | 00001c68 testl %eax,%eax 19 | 00001c6a jne 0x00001c63 20 | 00001c6c movl %ebx,0x0c(%esp) 21 | 00001c70 calll 0x00001c80 22 | 00001c75 movl %eax,(%esp) 23 | 00001c78 calll 0x00001f46 24 | 00001c7d hlt 25 | 00001c7e nop 26 | 00001c7f nop 27 | _main: 28 | 00001c80 pushl %ebp 29 | 00001c81 movl %esp,%ebp 30 | 00001c83 subl $0x08,%esp 31 | 00001c86 calll 0x00001ca0 32 | 00001c8b movl $0x00000001,0xf8(%ebp) 33 | 00001c92 movl 0xf8(%ebp),%eax 34 | 00001c95 movl %eax,0xfc(%ebp) 35 | 00001c98 movl 0xfc(%ebp),%eax 36 | 00001c9b addl $0x08,%esp 37 | 00001c9e popl %ebp 38 | 00001c9f ret 39 | _getOneValidDevice: 40 | 00001ca0 pushl %ebp 41 | 00001ca1 movl %esp,%ebp 42 | 00001ca3 subl $0x54,%esp 43 | 00001ca6 calll 0x00001cab 44 | 00001cab popl %eax 45 | 00001cac movl $0x00000000,0xcc(%ebp) 46 | 00001cb3 movl $0x00000000,0xd4(%ebp) 47 | 00001cba movl %eax,0xac(%ebp) 48 | 00001cbd jmp 0x00001ead 49 | 00001cc2 movl $0x00000000,0xd0(%ebp) 50 | 00001cc9 jmp 0x00001e98 51 | 00001cce movl $0x00000000,0xcc(%ebp) 52 | 00001cd5 jmp 0x00001e83 53 | 00001cda movl 0xd4(%ebp),%eax 54 | 00001cdd shll $0x10,%eax 55 | 00001ce0 movl 0xd0(%ebp),%ecx 56 | 00001ce3 shll $0x0b,%ecx 57 | 00001ce6 orl %ecx,%eax 58 | 00001ce8 movl 0xcc(%ebp),%ecx 59 | 00001ceb shll $0x08,%ecx 60 | 00001cee orl %ecx,%eax 61 | 00001cf0 orl $0x80000000,%eax 62 | 00001cf5 movl %eax,0xc4(%ebp) 63 | 00001cf8 movl 0xc4(%ebp),%eax 64 | 00001cfb movl $0x00000cf8,%ecx 65 | 00001d00 movl %ecx,%edx 66 | 00001d02 outl %eax,%dx 67 | 00001d03 movl $0x00000cfc,%eax 68 | 00001d08 movl %eax,%edx 69 | 00001d0a inl %dx,%eax 70 | 00001d0b movl %eax,0xbc(%ebp) 71 | 00001d0e movl 0xbc(%ebp),%eax 72 | 00001d11 movl %eax,0xdc(%ebp) 73 | 00001d14 movl 0xdc(%ebp),%eax 74 | 00001d17 movw %ax,0xc8(%ebp) 75 | 00001d1b movw 0xc8(%ebp),%ax 76 | 00001d1f movw %ax,0xda(%ebp) 77 | 00001d23 movw 0xc8(%ebp),%ax 78 | 00001d27 cmpw $0xff,%ax 79 | 00001d2b je 0x00001e7a 80 | 00001d31 movl 0xd4(%ebp),%eax 81 | 00001d34 shll $0x10,%eax 82 | 00001d37 movl 0xd0(%ebp),%ecx 83 | 00001d3a shll $0x0b,%ecx 84 | 00001d3d orl %ecx,%eax 85 | 00001d3f movl 0xcc(%ebp),%ecx 86 | 00001d42 shll $0x08,%ecx 87 | 00001d45 orl %ecx,%eax 88 | 00001d47 orl $0x80000000,%eax 89 | 00001d4c movl %eax,0xc4(%ebp) 90 | 00001d4f movl 0xc4(%ebp),%eax 91 | 00001d52 movl $0x00000cf8,%ecx 92 | 00001d57 movl %ecx,%edx 93 | 00001d59 outl %eax,%dx 94 | 00001d5a movl $0x00000cfc,%eax 95 | 00001d5f movl %eax,%edx 96 | 00001d61 inl %dx,%eax 97 | 00001d62 movl %eax,0xb8(%ebp) 98 | 00001d65 movl 0xb8(%ebp),%eax 99 | 00001d68 movl %eax,0xe4(%ebp) 100 | 00001d6b movl 0xe4(%ebp),%eax 101 | 00001d6e shrl $0x10,%eax 102 | 00001d71 movw %ax,0xca(%ebp) 103 | 00001d75 movw 0xca(%ebp),%ax 104 | 00001d79 movw %ax,0xe2(%ebp) 105 | 00001d7d movl 0xd4(%ebp),%eax 106 | 00001d80 shll $0x10,%eax 107 | 00001d83 movl 0xd0(%ebp),%ecx 108 | 00001d86 shll $0x0b,%ecx 109 | 00001d89 orl %ecx,%eax 110 | 00001d8b movl 0xcc(%ebp),%ecx 111 | 00001d8e shll $0x08,%ecx 112 | 00001d91 orl %ecx,%eax 113 | 00001d93 orl $0x80000008,%eax 114 | 00001d98 movl %eax,0xc4(%ebp) 115 | 00001d9b movl 0xc4(%ebp),%eax 116 | 00001d9e movl $0x00000cf8,%ecx 117 | 00001da3 movl %ecx,%edx 118 | 00001da5 outl %eax,%dx 119 | 00001da6 movl $0x00000cfc,%eax 120 | 00001dab movl %eax,%edx 121 | 00001dad inl %dx,%eax 122 | 00001dae movl %eax,0xb4(%ebp) 123 | 00001db1 movl 0xb4(%ebp),%eax 124 | 00001db4 movl %eax,0xec(%ebp) 125 | 00001db7 movl 0xec(%ebp),%eax 126 | 00001dba movw %ax,0xc2(%ebp) 127 | 00001dbe movw 0xc2(%ebp),%ax 128 | 00001dc2 movw %ax,0xea(%ebp) 129 | 00001dc6 movl 0xd4(%ebp),%eax 130 | 00001dc9 shll $0x10,%eax 131 | 00001dcc movl 0xd0(%ebp),%ecx 132 | 00001dcf shll $0x0b,%ecx 133 | 00001dd2 orl %ecx,%eax 134 | 00001dd4 movl 0xcc(%ebp),%ecx 135 | 00001dd7 shll $0x08,%ecx 136 | 00001dda orl %ecx,%eax 137 | 00001ddc orl $0x80000008,%eax 138 | 00001de1 movl %eax,0xc4(%ebp) 139 | 00001de4 movl 0xc4(%ebp),%eax 140 | 00001de7 movl $0x00000cf8,%ecx 141 | 00001dec movl %ecx,%edx 142 | 00001dee outl %eax,%dx 143 | 00001def movl $0x00000cfc,%eax 144 | 00001df4 movl %eax,%edx 145 | 00001df6 inl %dx,%eax 146 | 00001df7 movl %eax,0xb0(%ebp) 147 | 00001dfa movl 0xb0(%ebp),%eax 148 | 00001dfd movl %eax,0xf4(%ebp) 149 | 00001e00 movl 0xf4(%ebp),%eax 150 | 00001e03 shrl $0x10,%eax 151 | 00001e06 movw %ax,0xc0(%ebp) 152 | 00001e0a movw 0xc0(%ebp),%ax 153 | 00001e0e movw %ax,0xf2(%ebp) 154 | 00001e12 movw 0xc2(%ebp),%ax 155 | 00001e16 cmpw $0x10,%ax 156 | 00001e1a jne 0x00001e7a 157 | 00001e1c movw 0xc0(%ebp),%ax 158 | 00001e20 movzwl %ax,%eax 159 | 00001e23 andl $0x000000ff,%eax 160 | 00001e28 cmpl $0x00,%eax 161 | 00001e2b jne 0x00001e7a 162 | 00001e2d movl 0xd4(%ebp),%eax 163 | 00001e30 movw %ax,%dx 164 | 00001e33 int $0x82 165 | 00001e35 movl 0xd0(%ebp),%eax 166 | 00001e38 movw %ax,%dx 167 | 00001e3b int $0x82 168 | 00001e3d movl 0xcc(%ebp),%eax 169 | 00001e40 movw %ax,%dx 170 | 00001e43 int $0x82 171 | 00001e45 movw 0xca(%ebp),%ax 172 | 00001e49 movw %ax,%dx 173 | 00001e4c int $0x82 174 | 00001e4e movw 0xc8(%ebp),%ax 175 | 00001e52 movw %ax,%dx 176 | 00001e55 int $0x82 177 | 00001e57 movw 0xc2(%ebp),%ax 178 | 00001e5b movw %ax,%dx 179 | 00001e5e int $0x82 180 | 00001e60 movw 0xc0(%ebp),%ax 181 | 00001e64 movw %ax,%dx 182 | 00001e67 int $0x82 183 | 00001e69 int $0x83 184 | 00001e6b movl 0xac(%ebp),%eax 185 | 00001e6e leal 0x000002b9(%eax),%ecx 186 | 00001e74 movl %ecx,%edx 187 | 00001e76 int $0x84 188 | 00001e78 int $0x83 189 | 00001e7a movl 0xcc(%ebp),%eax 190 | 00001e7d addl $0x01,%eax 191 | 00001e80 movl %eax,0xcc(%ebp) 192 | 00001e83 movl 0xcc(%ebp),%eax 193 | 00001e86 cmpl $0x07,%eax 194 | 00001e89 jbe 0x00001cda 195 | 00001e8f movl 0xd0(%ebp),%eax 196 | 00001e92 addl $0x01,%eax 197 | 00001e95 movl %eax,0xd0(%ebp) 198 | 00001e98 movl 0xd0(%ebp),%eax 199 | 00001e9b cmpl $0x1f,%eax 200 | 00001e9e jbe 0x00001cce 201 | 00001ea4 movl 0xd4(%ebp),%eax 202 | 00001ea7 addl $0x01,%eax 203 | 00001eaa movl %eax,0xd4(%ebp) 204 | 00001ead movl 0xd4(%ebp),%eax 205 | 00001eb0 cmpl $0x000000ff,%eax 206 | 00001eb5 jbe 0x00001cc2 207 | 00001ebb movl 0xac(%ebp),%eax 208 | 00001ebe leal 0x000002d1(%eax),%ecx 209 | 00001ec4 movl %ecx,%edx 210 | 00001ec6 int $0x84 211 | 00001ec8 int $0x83 212 | 00001eca movl $0x00000000,0xf8(%ebp) 213 | 00001ed1 movl 0xf8(%ebp),%ecx 214 | 00001ed4 movl %ecx,0xfc(%ebp) 215 | 00001ed7 movl 0xfc(%ebp),%eax 216 | 00001eda movzwl %ax,%eax 217 | 00001edd addl $0x54,%esp 218 | 00001ee0 popl %ebp 219 | 00001ee1 ret 220 | 00001ee2 nop 221 | 00001ee3 nop 222 | 00001ee4 nop 223 | 00001ee5 nop 224 | 00001ee6 nop 225 | 00001ee7 nop 226 | 00001ee8 nop 227 | 00001ee9 nop 228 | 00001eea nop 229 | 00001eeb nop 230 | 00001eec nop 231 | 00001eed nop 232 | 00001eee nop 233 | 00001eef nop 234 | _memcpy: 235 | 00001ef0 pushl %ebp 236 | 00001ef1 movl %esp,%ebp 237 | 00001ef3 subl $0x1c,%esp 238 | 00001ef6 movl 0x10(%ebp),%eax 239 | 00001ef9 movl 0x0c(%ebp),%ecx 240 | 00001efc movl 0x08(%ebp),%edx 241 | 00001eff movl %edx,0xfc(%ebp) 242 | 00001f02 movl %ecx,0xf8(%ebp) 243 | 00001f05 movl %eax,0xf4(%ebp) 244 | 00001f08 movl 0xfc(%ebp),%eax 245 | 00001f0b movl %eax,0xe8(%ebp) 246 | 00001f0e movl 0xf8(%ebp),%eax 247 | 00001f11 movl %eax,0xe4(%ebp) 248 | 00001f14 jmp 0x00001f20 249 | 00001f16 movl 0xe4(%ebp),%eax 250 | 00001f19 movb (%eax),%al 251 | 00001f1b movl 0xe8(%ebp),%ecx 252 | 00001f1e movb %al,(%ecx) 253 | 00001f20 movl 0xf4(%ebp),%eax 254 | 00001f23 subl $0x01,%eax 255 | 00001f26 movl %eax,0xf4(%ebp) 256 | 00001f29 movl 0xf4(%ebp),%eax 257 | 00001f2c cmpl $0xff,%eax 258 | 00001f2f jne 0x00001f16 259 | 00001f31 movl 0xfc(%ebp),%eax 260 | 00001f34 movl %eax,0xec(%ebp) 261 | 00001f37 movl 0xec(%ebp),%eax 262 | 00001f3a movl %eax,0xf0(%ebp) 263 | 00001f3d movl 0xf0(%ebp),%eax 264 | 00001f40 addl $0x1c,%esp 265 | 00001f43 popl %ebp 266 | 00001f44 ret 267 | -------------------------------------------------------------------------------- /tools/wlinker.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define FILE_ERROR(fd, fmt, err...) { close(fd); printf(fmt, ##err); } 10 | 11 | struct my_nlist 12 | { 13 | int32_t n_strx; 14 | uint8_t n_type; 15 | uint8_t n_sect; 16 | int16_t n_desc; 17 | uint32_t n_value; 18 | }; 19 | 20 | int main(int argc, char* argv[]) 21 | { 22 | int fd = -1; 23 | int fd_head = -1; 24 | struct mach_header head; 25 | int ret = -1; 26 | struct load_command cmd; 27 | int i = 0; 28 | struct segment_command seg_cmd; 29 | struct section sect; 30 | struct symtab_command sym_cmd; 31 | struct my_nlist sym_nlist; 32 | int isect = 0; 33 | int f_pos = 0; 34 | char buf[102400]; 35 | int ibuf = 0; 36 | int fd_out = -1; 37 | int head_size = -1; 38 | char system_image[102400]; // 100K 39 | int i_nsyms = 0; 40 | unsigned int start_address = 0; 41 | 42 | if (argc != 3) { 43 | printf("Use: %s [head.s filename] [mach-o filename]\n", argv[0]); 44 | return -1; 45 | } 46 | // deal system file 47 | fd = open(argv[2], O_RDONLY); 48 | if(fd < 0) { 49 | printf("open system file failed\n"); 50 | return -1; 51 | } 52 | 53 | ret = read(fd, &head, sizeof(head)); 54 | if(ret != sizeof(head)) { 55 | FILE_ERROR(fd, "%s", "read file failed\n"); 56 | return -1; 57 | } 58 | 59 | printf("head info: magic(%x) filetype(%d) ncmds(%d) sizeofcmds(%d) flags(%x)\n", 60 | head.magic, head.filetype, head.ncmds, head.sizeofcmds, head.flags); 61 | 62 | if(head.magic != MH_MAGIC) { 63 | FILE_ERROR(fd, "%s", "[ERROR] This program just supports 32-bit mach-o file, please use [gcc -m32] for compile.\n"); 64 | return -1; 65 | } 66 | 67 | // printf("Commands: LC_UUID(%d) LC_SEGMENT(%d) LC_SEGMENT_64(%d) \n", 68 | // LC_UUID, LC_SEGMENT,LC_SEGMENT_64); 69 | 70 | // printf("sizeof(segment_command): %lu \n", sizeof(struct segment_command)); 71 | // printf("sizeof(segment_command_64): %lu \n", sizeof(struct segment_command_64)); 72 | 73 | for(i=0; i