You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

startmpcc.S 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. /* #defines because ljmp wants a number, probably gas bug */
  2. /* .equ KERN_CODE_SEG,_pmcs-_gdt */
  3. #define KERN_CODE_SEG 0x08
  4. .equ KERN_DATA_SEG,_pmds-_gdt
  5. /* .equ REAL_CODE_SEG,_rmcs-_gdt */
  6. #define REAL_CODE_SEG 0x18
  7. .equ REAL_DATA_SEG,_rmds-_gdt
  8. .equ CR0_PE,1
  9. #ifdef GAS291
  10. #define DATA32 data32;
  11. #define ADDR32 addr32;
  12. #define LJMPI(x) ljmp x
  13. #else
  14. #define DATA32 data32
  15. #define ADDR32 addr32
  16. /* newer GAS295 require #define LJMPI(x) ljmp *x */
  17. #define LJMPI(x) ljmp x
  18. #endif
  19. #define PIC1_VBS 0x08 /* PIC1 interrupts start at vector 64 */
  20. #define PIC2_VBS 0x70 /* PIC1 interrupts start at vector 112 */
  21. /*
  22. * NOTE: if you write a subroutine that is called from C code (gcc/egcs),
  23. * then you only have to take care of %ebx, %esi, %edi and %ebp. These
  24. * registers must not be altered under any circumstance. All other registers
  25. * may be clobbered without any negative side effects. If you don't follow
  26. * this rule then you'll run into strange effects that only occur on some
  27. * gcc versions (because the register allocator may use different registers).
  28. *
  29. * All the data32 prefixes for the ljmp instructions are necessary, because
  30. * the assembler emits code with a relocation address of 0. This means that
  31. * all destinations are initially negative, which the assembler doesn't grok,
  32. * because for some reason negative numbers don't fit into 16 bits. The addr32
  33. * prefixes are there for the same reasons, because otherwise the memory
  34. * references are only 16 bit wide. Theoretically they are all superfluous.
  35. * One last note about prefixes: the data32 prefixes on all call _real_to_prot
  36. * instructions could be removed if the _real_to_prot function is changed to
  37. * deal correctly with 16 bit return addresses. I tried it, but failed.
  38. */
  39. /**************************************************************************
  40. START - Where all the fun begins....
  41. **************************************************************************/
  42. /* this must be the first thing in the file because we enter from the top */
  43. .global _start
  44. .code32
  45. _start:
  46. cli
  47. /* load new IDT and GDT */
  48. lgdt gdtarg
  49. lidt Idt_Reg
  50. /* flush prefetch queue, and reload %cs:%eip */
  51. ljmp $KERN_CODE_SEG,$1f
  52. 1:
  53. /* reload other segment registers */
  54. movl $KERN_DATA_SEG,%eax
  55. movl %eax,%ds
  56. movl %eax,%es
  57. movl %eax,%ss
  58. movl $stktop,%esp
  59. /* program the PITs in order to stop them */
  60. mov $0x30,%al
  61. out %al,$0x43
  62. out %al,$0x40
  63. mov $0x70,%al
  64. out %al,$0x43
  65. out %al,$0x41
  66. mov $0xf0,%al
  67. out %al,$0x43
  68. out %al,$0x42
  69. call main
  70. /* fall through */
  71. .globl exit
  72. exit:
  73. 2:
  74. ljmp $KERN_CODE_SEG,$2b
  75. /**************************************************************************
  76. MEMSIZE - Determine size of extended memory
  77. **************************************************************************/
  78. .globl memsize
  79. memsize:
  80. #if 0
  81. pushl %ebx
  82. pushl %esi
  83. pushl %edi
  84. call _prot_to_real
  85. .code16
  86. movw $0xe801,%ax
  87. stc
  88. int $0x15
  89. jc 1f
  90. andl $0xffff,%eax
  91. andl $0xffff,%ebx
  92. shll $6,%ebx
  93. addl %ebx,%eax
  94. jmp 2f
  95. 1:
  96. movw $0x8800,%ax
  97. int $0x15
  98. andl $0xffff,%eax
  99. 2:
  100. movl %eax,%esi
  101. DATA32 call _real_to_prot
  102. .code32
  103. movl %esi,%eax
  104. popl %edi
  105. popl %esi
  106. popl %ebx
  107. #else
  108. mov $32768,%eax
  109. #endif
  110. ret
  111. /**************************************************************************
  112. XSTART - Transfer control to the kernel just loaded
  113. **************************************************************************/
  114. .code16
  115. .globl _int08_handler
  116. _int08_handler:
  117. movb $0x20, %al
  118. outb %al, $0x20
  119. iret
  120. .globl _int10_handler
  121. _int10_handler:
  122. cmp $0x3, %ah
  123. jnz _int10_04
  124. mov $0x0, %dx
  125. mov $0x0, %cx
  126. iret
  127. _int10_04:
  128. cmp $0x4, %ah
  129. jnz _int10_05
  130. mov $0x0, %ah
  131. iret
  132. _int10_05:
  133. cmp $0x5, %ah
  134. jnz _int10_08
  135. mov $0x0, %al
  136. iret
  137. _int10_08:
  138. cmp $0x8, %ah
  139. jnz _int10_0D
  140. mov $0x20, %al
  141. mov $0x7, %ah
  142. iret
  143. _int10_0D:
  144. cmp $0xD, %ah
  145. jnz _int10_0F
  146. mov $0x0, %al
  147. iret
  148. _int10_0F:
  149. cmp $0xF, %ah
  150. jnz _int10_XX
  151. mov $0xb, %al
  152. mov $80, %ah
  153. mov $0, %bh
  154. _int10_XX:
  155. iret
  156. .globl _int11_handler
  157. _int11_handler:
  158. mov $0x22, %ax
  159. iret
  160. .globl _int12_handler
  161. _int12_handler:
  162. mov $640, %ax
  163. iret
  164. .globl _int13_handler
  165. _int13_handler:
  166. clc
  167. mov $0, %ah
  168. iret
  169. .globl _int14_handler
  170. _int14_handler:
  171. iret
  172. .globl _int15_handler
  173. _int15_handler:
  174. cmp $0xe801,%ax
  175. jz _int15_008
  176. cmp $0x0, %ah
  177. jz _int15_000
  178. cmp $0x1, %ah
  179. jz _int15_000
  180. cmp $0x2, %ah
  181. jz _int15_000
  182. cmp $0x3, %ah
  183. jz _int15_000
  184. cmp $0xf, %ah
  185. jz _int15_000
  186. cmp $0x21, %ah
  187. jz _int15_000
  188. cmp $0x40, %ah
  189. jz _int15_000
  190. cmp $0x41, %ah
  191. jz _int15_000
  192. cmp $0x42, %ah
  193. jz _int15_000
  194. cmp $0x43, %ah
  195. jz _int15_000
  196. cmp $0x44, %ah
  197. jz _int15_000
  198. cmp $0x80, %ah
  199. jz _int15_001
  200. cmp $0x81, %ah
  201. jz _int15_001
  202. cmp $0x82, %ah
  203. jz _int15_002
  204. cmp $0x83, %ah
  205. jz _int15_003
  206. cmp $0x84, %ah
  207. jz _int15_000
  208. cmp $0x85, %ah
  209. jz _int15_004
  210. cmp $0x86, %ah
  211. jz _int15_003
  212. cmp $0x87, %ah
  213. jz _int15_005
  214. cmp $0x88, %ah
  215. jz _int15_006
  216. cmp $0x89, %ah
  217. jz _int15_005
  218. cmp $0x90, %ah
  219. jz _int15_007
  220. cmp $0xc0, %ah
  221. jz _int15_000
  222. cmp $0xc1, %ah
  223. jz _int15_000
  224. cmp $0xc2, %ah
  225. jz _int15_000
  226. cmp $0xc3, %ah
  227. jz _int15_000
  228. cmp $0xc4, %ah
  229. jz _int15_000
  230. iret
  231. _int15_000:
  232. mov $0x86, %ah
  233. stc
  234. iret
  235. _int15_001:
  236. mov $0, %bx
  237. mov $0, %cx
  238. iret
  239. _int15_002:
  240. mov $0, %bx
  241. iret
  242. _int15_003:
  243. clc
  244. iret
  245. _int15_004:
  246. mov $0, %al
  247. iret
  248. _int15_005:
  249. mov $0, %ah
  250. clc
  251. cmp $0, %ah
  252. iret
  253. _int15_006:
  254. mov $0xf000, %ax
  255. iret
  256. _int15_007:
  257. stc
  258. iret
  259. _int15_008:
  260. clc
  261. mov $1024, %dx /* dx -> extended memory size (in 64K chuncks) */
  262. mov $640, %cx /* cx -> conventional memory size (in 1 Kbytes chuncks) */
  263. iret
  264. .globl _int16_handler
  265. _int16_handler:
  266. cmp $0x0, %ah
  267. jnz _int16_01
  268. mov $0x20, %al
  269. mov $0x39, %ah
  270. iret
  271. _int16_01:
  272. cmp $0x1, %ah
  273. jnz _int16_02
  274. iret
  275. _int16_02:
  276. cmp $0x2, %ah
  277. jnz _int16_05
  278. mov $0, %al
  279. iret
  280. _int16_05:
  281. cmp $0x5, %ah
  282. jnz _int16_10
  283. mov $0, %al
  284. iret
  285. _int16_10:
  286. cmp $0x10, %ah
  287. jnz _int16_11
  288. mov $0x20, %al
  289. mov $0x39, %ah
  290. iret
  291. _int16_11:
  292. cmp $0x11, %ah
  293. jnz _int16_12
  294. iret
  295. _int16_12:
  296. cmp $0x12, %ah
  297. jnz _int16_XX
  298. mov $0, %ax
  299. iret
  300. _int16_XX:
  301. iret
  302. .globl _int17_handler
  303. _int17_handler:
  304. mov $0xd0, %ah
  305. iret
  306. .globl _int19_handler
  307. _int19_handler:
  308. hlt
  309. iret
  310. .globl _int1A_handler
  311. _int1A_handler:
  312. stc
  313. iret
  314. .code32
  315. .globl xstart
  316. xstart:
  317. /* reprogram the PICs so that interrupt are masked */
  318. movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/
  319. outb %al,$0x20
  320. movb $PIC1_VBS, %al
  321. outb %al,$0x21
  322. movb $0x4,%al
  323. outb %al,$0x21
  324. movb $0x1,%al
  325. outb %al,$0x21
  326. movb $0xff,%al
  327. outb %al,$0x21
  328. movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/
  329. outb %al,$0xa0
  330. movb $PIC2_VBS, %al
  331. outb %al,$0xa1
  332. movb $0x2,%al
  333. outb %al,$0xa1
  334. movb $0x1,%al
  335. outb %al,$0xa1
  336. movb $0xff,%al
  337. outb %al,$0xa1
  338. pushl %ebp
  339. movl %esp,%ebp
  340. pushl %ebx
  341. pushl %esi
  342. pushl %edi
  343. movl 8(%ebp),%eax
  344. movl %eax,_execaddr
  345. movl 12(%ebp),%ebx
  346. movl 16(%ebp),%ecx /* bootp record (32bit pointer) */
  347. addl $28,%ecx /* ip, udp header */
  348. shll $12,%ecx
  349. shrw $12,%cx
  350. call _prot_to_real
  351. .code16
  352. /* MP: add int10 handler */
  353. push %eax
  354. push %ebx
  355. push %es
  356. mov $0,%ax
  357. mov %ax,%es
  358. mov %cs,%ax
  359. shl $16,%eax
  360. ADDR32 mov $(_int08_handler-_start),%ax
  361. mov $0x20,%ebx
  362. mov %eax,%es:(%bx)
  363. ADDR32 mov $(_int10_handler-_start),%ax
  364. mov $0x40,%ebx
  365. mov %eax,%es:(%bx)
  366. ADDR32 mov $(_int11_handler-_start),%ax
  367. mov $0x44,%ebx
  368. mov %eax,%es:(%bx)
  369. ADDR32 mov $(_int12_handler-_start),%ax
  370. mov $0x48,%ebx
  371. mov %eax,%es:(%bx)
  372. ADDR32 mov $(_int13_handler-_start),%ax
  373. mov $0x4c,%ebx
  374. mov %eax,%es:(%bx)
  375. ADDR32 mov $(_int14_handler-_start),%ax
  376. mov $0x50,%ebx
  377. mov %eax,%es:(%bx)
  378. ADDR32 mov $(_int15_handler-_start),%ax
  379. mov $0x54,%ebx
  380. mov %eax,%es:(%bx)
  381. ADDR32 mov $(_int16_handler-_start),%ax
  382. mov $0x58,%ebx
  383. mov %eax,%es:(%bx)
  384. ADDR32 mov $(_int17_handler-_start),%ax
  385. mov $0x5c,%ebx
  386. mov %eax,%es:(%bx)
  387. ADDR32 mov $(_int19_handler-_start),%ax
  388. mov $0x64,%ebx
  389. mov %eax,%es:(%bx)
  390. ADDR32 mov $(_int1A_handler-_start),%ax
  391. mov $0x68,%ebx
  392. mov %eax,%es:(%bx)
  393. pop %es
  394. pop %ebx
  395. pop %eax
  396. /* */
  397. pushl %ecx /* bootp record */
  398. pushl %ebx /* file header */
  399. movl $((RELOC<<12)+(1f-RELOC)),%eax
  400. pushl %eax
  401. ADDR32 LJMPI(_execaddr-_start)
  402. 1:
  403. addw $8,%sp /* XXX or is this 10 in case of a 16bit "ret" */
  404. DATA32 call _real_to_prot
  405. .code32
  406. popl %edi
  407. popl %esi
  408. popl %ebx
  409. popl %ebp
  410. ret
  411. _execaddr:
  412. .long 0
  413. #ifdef IMAGE_MULTIBOOT
  414. /**************************************************************************
  415. XEND - Restart Etherboot from the beginning (from protected mode)
  416. **************************************************************************/
  417. .globl xend
  418. xend:
  419. cs
  420. lidt idtarg_realmode-_start+RELOC
  421. cs
  422. lgdt gdtarg-_start+RELOC
  423. #ifdef GAS291
  424. ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */
  425. #else
  426. ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */
  427. #endif /* GAS291 */
  428. 1:
  429. .code16
  430. movw $REAL_DATA_SEG,%ax
  431. movw %ax,%ds
  432. movw %ax,%ss
  433. movw %ax,%es
  434. /* clear the PE bit of CR0 */
  435. movl %cr0,%eax
  436. andl $0!CR0_PE,%eax
  437. movl %eax,%cr0
  438. /* make intersegment jmp to flush the processor pipeline
  439. * and reload %cs:%eip (to clear upper 16 bits of %eip).
  440. */
  441. DATA32 ljmp $(RELOC)>>4,$2f-_start
  442. 2:
  443. /* we are in real mode now
  444. * set up the real mode segment registers : %ds, %ss, %es
  445. */
  446. movw %cs,%ax
  447. movw %ax,%ds
  448. movw %ax,%es
  449. movw %ax,%ss
  450. xorl %esp,%esp
  451. ADDR32 movw initsp-RELOC,%sp
  452. movw $0,%ax
  453. movw %ax,%fs
  454. movw %ax,%gs
  455. sti
  456. jmp _start
  457. .code32
  458. #endif /* IMAGE_MULTIBOOT */
  459. .global get_cs
  460. get_cs:
  461. xorl %eax,%eax
  462. movw %cs,%ax
  463. ret
  464. .global get_ds
  465. get_ds:
  466. xorl %eax,%eax
  467. movw %ds,%ax
  468. ret
  469. .global getsp
  470. getsp:
  471. movl %esp,%eax /* GET STACK POINTER */
  472. subl $4, %eax /* ACCOUNT FOR RETURN ADDRESS ON */
  473. ret
  474. .global get_gdtbase
  475. get_gdtbase:
  476. sub $8,%esp /* ALLOCATE ROOM ON THE STACK */
  477. sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */
  478. mov 2(%esp),%eax /* READ GDT BASE ADDRESS */
  479. mov $KERN_DATA_SEG,%dx /* ASSUME UNIVERSAL DS. */
  480. add $8,%esp /* RESTORE STACK */
  481. ret /* DONE */
  482. .global get_gdtsize
  483. get_gdtsize:
  484. sub $8,%esp /* ALLOCATE ROOM ON THE STACK */
  485. sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */
  486. xor %eax,%eax
  487. mov 2(%esp),%eax /* READ GDT BASE ADDRESS */
  488. mov (%ESP),%ax
  489. shr $3,%ax
  490. add $8,%esp /* RESTORE STACK */
  491. ret /* DONE */
  492. .global get_idtbase
  493. get_idtbase:
  494. sub $8,%esp
  495. sidt (%esp,1) /* STORE IIDT REGISTER ON STACK */
  496. mov 2(%esp),%eax
  497. mov $KERN_DATA_SEG,%dx
  498. add $8,%esp
  499. ret
  500. .global get_lw
  501. get_lw:
  502. xor %edx,%edx
  503. mov 8(%esp),%eax
  504. mov 4(%esp),%dx
  505. ret
  506. /**************************************************************************
  507. SETJMP - Save stack context for non-local goto
  508. **************************************************************************/
  509. .globl setjmp
  510. setjmp:
  511. mov 4(%esp),%ecx
  512. mov 0(%esp),%edx
  513. mov %edx,0(%ecx)
  514. mov %ebx,4(%ecx)
  515. mov %esp,8(%ecx)
  516. mov %ebp,12(%ecx)
  517. mov %esi,16(%ecx)
  518. mov %edi,20(%ecx)
  519. mov %eax,24(%ecx)
  520. mov $0,%eax
  521. ret
  522. /**************************************************************************
  523. LONGJMP - Non-local jump to a saved stack context
  524. **************************************************************************/
  525. .globl longjmp
  526. longjmp:
  527. mov 4(%esp),%edx
  528. mov 8(%esp),%eax
  529. mov 0(%edx),%ecx
  530. mov 4(%edx),%ebx
  531. mov 8(%edx),%esp
  532. mov 12(%edx),%ebp
  533. mov 16(%edx),%esi
  534. mov 20(%edx),%edi
  535. cmp $0,%eax
  536. jne 1f
  537. mov $1,%eax
  538. 1: mov %ecx,0(%esp)
  539. ret
  540. /**************************************************************************
  541. _REAL_TO_PROT - Go from REAL mode to Protected Mode
  542. **************************************************************************/
  543. .globl _real_to_prot
  544. _real_to_prot:
  545. .code16
  546. cli
  547. cs
  548. ADDR32 lgdt gdtarg-_start
  549. movl %cr0,%eax
  550. orl $CR0_PE,%eax
  551. movl %eax,%cr0 /* turn on protected mode */
  552. /* flush prefetch queue, and reload %cs:%eip */
  553. DATA32 ljmp $KERN_CODE_SEG,$1f
  554. 1:
  555. .code32
  556. /* reload other segment registers */
  557. movl $KERN_DATA_SEG,%eax
  558. movl %eax,%ds
  559. movl %eax,%es
  560. movl %eax,%ss
  561. addl $RELOC,%esp /* Fix up stack pointer */
  562. xorl %eax,%eax
  563. movl %eax,%fs
  564. movl %eax,%gs
  565. popl %eax /* Fix up return address */
  566. addl $RELOC,%eax
  567. pushl %eax
  568. ret
  569. /**************************************************************************
  570. _PROT_TO_REAL - Go from Protected Mode to REAL Mode
  571. **************************************************************************/
  572. .globl _prot_to_real
  573. _prot_to_real:
  574. .code32
  575. popl %eax
  576. subl $RELOC,%eax /* Adjust return address */
  577. pushl %eax
  578. subl $RELOC,%esp /* Adjust stack pointer */
  579. #ifdef GAS291
  580. ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */
  581. #else
  582. ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */
  583. #endif /* GAS291 */
  584. 1:
  585. .code16
  586. movw $REAL_DATA_SEG,%ax
  587. movw %ax,%ds
  588. movw %ax,%ss
  589. movw %ax,%es
  590. movw %ax,%fs
  591. movw %ax,%gs
  592. cli
  593. /* clear the PE bit of CR0 */
  594. movl %cr0,%eax
  595. andl $0!CR0_PE,%eax
  596. movl %eax,%cr0
  597. /* make intersegment jmp to flush the processor pipeline
  598. * and reload %cs:%eip (to clear upper 16 bits of %eip).
  599. */
  600. DATA32 ljmp $(RELOC)>>4,$2f-_start
  601. 2:
  602. /* we are in real mode now
  603. * set up the real mode segment registers : %ds, $ss, %es
  604. */
  605. movw %cs,%ax
  606. movw %ax,%ds
  607. movw %ax,%es
  608. movw %ax,%ss
  609. #if 0
  610. sti
  611. #endif
  612. DATA32 ret /* There is a 32 bit return address on the stack */
  613. .code32
  614. /**************************************************************************
  615. GLOBAL DESCRIPTOR TABLE
  616. **************************************************************************/
  617. .align 4
  618. Idt_Reg:
  619. .word 0x3ff
  620. .long 0
  621. .align 4
  622. _gdt:
  623. gdtarg:
  624. Gdt_Table:
  625. .word 0x27 /* limit */
  626. .long _gdt /* addr */
  627. .word 0
  628. _pmcs:
  629. /* 32 bit protected mode code segment */
  630. .word 0xffff,0
  631. .byte 0,0x9f,0xcf,0
  632. _pmds:
  633. /* 32 bit protected mode data segment */
  634. .word 0xffff,0
  635. .byte 0,0x93,0xcf,0
  636. _rmcs:
  637. /* 16 bit real mode code segment */
  638. .word 0xffff,(RELOC&0xffff)
  639. .byte (RELOC>>16),0x9b,0x00,(RELOC>>24)
  640. _rmds:
  641. /* 16 bit real mode data segment */
  642. .word 0xffff,(RELOC&0xffff)
  643. .byte (RELOC>>16),0x93,0x00,(RELOC>>24)
  644. .align 4
  645. RUN_GDT: /* POINTER TO GDT IN RAM */
  646. .byte 0x7f,0 /* [BSP_GDT_NUM*8]-1 */
  647. .long Gdt_Table
  648. .align 4
  649. .section ".rodata"
  650. err_not386:
  651. .ascii "Etherboot/32 requires 386+"
  652. .byte 0x0d, 0x0a
  653. err_not386_end:
  654. days: .long 0
  655. irq_num: .long
  656. .data
  657. .align 4
  658. .org 2048
  659. .global stktop
  660. stktop:
  661. .long
  662. .section ".armando"
  663. /*                1:::::::::2:::::::::3:::::::3 */
  664. /*        12345678901234567890123456789012345678 */
  665. /*       v----+----v----+----v----+----v----+--- */
  666. .global EtherbootString
  667. EtherbootString:
  668. .ascii "EtherBoot MPCC " /* fw identifier */
  669. .byte 0, 0 /* mandatory hole */
  670. .long _start /* entry point */
  671. .word 0
  672. .byte 'E' /* type */
  673. .byte 0 /* selector */
  674. .word 0 /* CRC */