OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [lib/] [libbsp/] [i386/] [ts_386ex/] [tools/] [dos_sup/] [loader_hybrid_com.asm] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
; loader_hybrid_com.asm
2
;
3
; This is a DOS command-line loader for RTEMS executables running on
4
; the Technologic Systems TS-1325 Embedded PC.
5
;
6
; It loads a DOS file given on the command line to the address `KernelBase',
7
; and then transfers control there. It uses DOS file I/O commands to read from
8
; the A: flash disk, and direct memory access to read from the C: ramdisk.
9
;
10
; Copying uses protected flat mode, so kernelbase could be above 1MB.
11
; It does not initialize protected mode before transferring control
12
; to the RTEMS executable image.
13
;
14
; Compile with: nasm -o loader.com loader_hybrid_com.asm
15
;
16
; Tony Ambardar (c) 1999
17
; E.C.E. Department
18
; University of British Columbia
19
 
20
%include "ts1325.inc"    ; Some useful LED and button macros
21
 
22
; IMPORTANT: [org xxx] MUST be the same as RelocAddr below.
23
 
24
[org E000h]
25
[bits 16]
26
 
27
; Only these three definitions may need to change
28
 
29
KernelBase equ  08000h   ; Where (32-bit) to locate and run RTEMS executable
30
 
31
RelocSeg   equ  9000h    ; Segment to relocate code.
32
RelocAddr  equ  0E000h   ; Address to relocate code, same as "org" above
33
 
34
; Next three used in GDT
35
 
36
RelocBase  equ  RelocSeg*16
37
Reloc15    equ  RelocBase & 0FFFFh
38
Reloc23    equ  RelocBase / 10000h
39
 
40
Buffer     equ  RelocAddr+400h   ; In same segment as RelocSeg
41
BuffSiz    equ  200h             ; Size of disk read + copy
42
 
43
StackSeg   equ  RelocSeg
44
StackSiz   equ  40h
45
StackAddr  equ  Buffer+BuffSiz+StackSiz
46
 
47
; Used to jump to kernel in real mode
48
 
49
KernelAddr equ  KernelBase & 0FFFFh
50
KernelSeg  equ  (KernelBase - KernelAddr) / 16
51
 
52
; Used to load from the ramdisk
53
 
54
Extended   equ  100000h  ; Start of extended memory / C: ramdisk
55
OffsetBPB  equ  0Bh      ; Start of BIOS param block in bootsector
56
 
57
; Command-line parameters
58
 
59
ParamLen   equ  80h      ; Byte length of command line params
60
ParamStr   equ  82h      ; Start of param string
61
 
62
; The ORG address above means pre-relocation addresses are wrong. The
63
; following macro fixes these up.
64
 
65
%define PRE_RELOC_ADDR(addr) (addr-CodeStart+100h)
66
 
67
CodeStart:
68
 
69
mov  dx, PRE_RELOC_ADDR(Greet)
70
mov  ah, 9h
71
int  21h
72
 
73
mov  ax, 0b021h       ; Exit to DOS if push-button switch pressed
74
int  15h
75
and  al, 01h          ; Bit 0 == 0 if button pressed
76
jz   ButtonExit
77
 
78
xor cx, cx
79
mov cl, [ParamLen]   ; See if there is a command line arg
80
jcxz NameError
81
 
82
dec  cx              ; Nix leading space. Is this standard?
83
cmp  cx, 12          ; Limit to 12 chars: e.g. ABCDEFGH.IJK
84
jg   NameError
85
                     ; Damn. Should make sure of no ':' or '\' chars too.
86
 
87
; Required by "relocated" [org] statement above
88
 
89
mov  di, PRE_RELOC_ADDR(FName)
90
mov  si, ParamStr
91
repne
92
movsb                ; Copy command line arg
93
 
94
; Make sure no ':' in filename. This forces using the default dir.
95
 
96
mov  di, PRE_RELOC_ADDR(FName)
97
mov  al, ':'
98
mov  cx, 12
99
repne
100
scasb
101
je   NameError
102
 
103
jmp  Relocate
104
 
105
ButtonExit:
106
mov  dx, PRE_RELOC_ADDR(Button)
107
jmp short  DosPrint
108
 
109
NameError:
110
mov  dx, PRE_RELOC_ADDR(FError)
111
jmp short  DosPrint
112
 
113
DosError:            ; Only call this AFTER relocation
114
mov  dx, RError
115
 
116
DosPrint:
117
mov  ah, 9h
118
int  21h
119
 
120
DosExit:
121
mov  ax, 04C00h      ; DOS Function: Exit program
122
int  21h             ; Call DOS. Terminate Program
123
 
124
Relocate:            ; Move this code down to RelocAddr
125
 
126
cld
127
mov  ax, RelocSeg
128
mov  es, ax           ; Set destination = RelocSeg:RelocAddr
129
mov  di, RelocAddr
130
mov  si, 100h         ; Source is ds:0100h i.e. a COM file
131
mov  cx, CodeEnd - CodeStart ; Size of all code
132
 
133
repne
134
movsb
135
 
136
; continue in copied code
137
 
138
jmp  RelocSeg:RelocAddr + (RelocStart - CodeStart)
139
 
140
RelocStart:
141
cli
142
mov  ax, StackSeg
143
mov  ss, ax
144
mov  sp, StackAddr
145
mov  ax, cs
146
mov  ds, ax
147
mov  es, ax          ; Setup segments and stack
148
sti
149
 
150
mov  ah, 19h
151
int  21h
152
mov  [DDrive], al    ; Save current default drive
153
 
154
mov  ax, 3d00h       ; DOS Function: Open the file for reading
155
mov  dx, FName       ; Presume DS points at filename segment
156
int  21h
157
jc   DosError
158
 
159
GoodOpen:
160
mov  [FHndl], ax     ; Save file handle
161
 
162
mov  al, [DDrive]    ; Check if loading from C: drive (ramdisk)
163
cmp  al, 2
164
je   LoadRamdisk
165
 
166
LoadDosdisk:
167
 
168
; Here we are loading from A: drive. Use DOS calls to load the file into
169
; extended memory. Then copy from extended memory to `KernelBase'. This way
170
; we avoid overwriting DOS file I/O structures if reading directly into
171
; conventional (<640K) memory.
172
 
173
mov  edi, Extended   ; Destination for code read @ 1 Meg
174
 
175
ReadLoop:
176
 
177
mov  ah,3fh          ; DOS Function: Read data from the file
178
mov  bx, [FHndl]
179
mov  dx, Buffer      ; Address of data buffer
180
mov  cx, BuffSiz     ; Request BuffSiz bytes
181
int  21h
182
jc   DosError
183
 
184
GoodRead:
185
 
186
cmp  ax, cx          ; EOF reached? AX = # bytes read
187
pushf
188
 
189
add  ax, 3
190
shr  ax, 2           ; Copy buffer by dwords, # = (ax + 3)/4
191
movzx  ecx, ax
192
mov  esi, RelocBase + Buffer     ; Source for copy, destination is in edi
193
 
194
call CopyData32      ; Do protected-mode copy
195
 
196
popf
197
je   ReadLoop        ; Still data left, so read next chunk
198
 
199
mov  esi, Extended   ; Source for copy @ 1 Meg
200
mov  ecx, edi        ; Make count in dwords
201
sub  ecx, esi
202
add  ecx, 3
203
shr  ecx, 2
204
mov  edi, KernelBase ; Destination copy
205
 
206
call CopyData32      ; Move code into conventional memory
207
jmp  RunKernel
208
 
209
LoadRamdisk:
210
 
211
; Here we are loading from C: drive. Use protected mode to directly access
212
; the virtual disk sectors in extended memory and copy to `KernelBase'.
213
; This way we avoid using DOS file I/O calls, except for an `open' earlier
214
; which tells us the file exists.
215
 
216
; Copy C: "bootsector" to buffer and save the BIOS parameter block
217
 
218
mov  esi, Extended
219
mov  edi, RelocBase + Buffer     ; Must be a 32-but address...
220
mov  ecx, 80h
221
call CopyData32
222
 
223
mov  si, Buffer + OffsetBPB
224
mov  di, SavBPB
225
mov  cx, EndBPB - SavBPB
226
repne
227
movsb
228
 
229
; Calculate  FAT, root dir, and data start addresses for the ramdisk
230
 
231
xor  eax, eax
232
mov  ebx, eax
233
mov  ecx, ebx
234
 
235
mov  ax, [ResSec]
236
 
237
mov  bl, [NumFAT]
238
imul bx, [SecFAT]
239
 
240
mov  cx, [NRoot]
241
shr  cx, 4           ; 10h directory entries per sector
242
 
243
add  bx, ax
244
add  cx, bx
245
 
246
mov  dx, [BpSect]
247
imul ax, dx
248
imul bx, dx
249
imul cx, dx
250
 
251
add  eax, Extended
252
add  ebx, Extended
253
add  ecx, Extended
254
 
255
mov  [BegFAT], eax
256
mov  [BegRoot], ebx
257
mov  [BegData], ecx
258
 
259
; Convert the saved filename to format used in directory entry. Assume
260
; there's a `.' in it. Hopefully this won't haunt us later...
261
 
262
mov  di, FName       ; Find the `.'
263
mov  al, '.'
264
mov  cx, 12
265
repne
266
scasb
267
 
268
mov  bx, di          ; di points to filename extension
269
 
270
mov  di, DirName
271
mov  si, FName
272
mov  cx, bx          ; Make count
273
sub  cx, si
274
dec cx
275
repne                ; Copy initial part of filename
276
movsb
277
 
278
mov  di, bx          ; Find the terminating zero
279
xor  al,al
280
mov  cx, 4
281
repne
282
scasb
283
 
284
mov  cx, di          ; Make count
285
sub  cx, bx
286
dec  cx
287
mov  si, bx
288
mov  di, DirName + 8
289
repne                ; Copy filename extension
290
movsb
291
 
292
mov  si, DirName     ; Convert the stupid thing to upper case
293
mov  di, si
294
mov  cx, 11
295
 
296
Cvt2Upper:
297
 
298
lodsb
299
cmp  al, 'a'
300
jb   NotLow
301
cmp  al, 'z'
302
ja   NotLow
303
xor  al, 20h
304
 
305
NotLow:
306
 
307
stosb
308
loop Cvt2Upper
309
 
310
; Now load in the root directory (temporarily) to find the first cluster
311
; of our file. Use KernelSeg:KernelAddr as temporary storage.
312
 
313
mov  esi, [BegRoot]
314
mov  edi, KernelBase
315
xor  ecx, ecx
316
mov  cx, [NRoot]
317
shl  cx, 3           ; Each root entry is 8 dwords
318
call CopyData32
319
 
320
mov  dx, [NRoot]     ; Max # of dir entries
321
 
322
mov  cx, KernelSeg   ; Setup segment selector for comparison
323
mov  es, cx
324
mov  di, KernelAddr
325
 
326
FindEntry:
327
 
328
mov  cx, 11
329
mov  si, DirName
330
push di
331
rep  cmpsb
332
pop  di
333
je   GotEntry
334
add  di, 20h         ; Point to next dir entry
335
dec  dx
336
jnz  FindEntry
337
 
338
int  3h              ; Should never get here...
339
 
340
GotEntry:
341
 
342
mov  eax, KernelBase ; Setup initial address for copy
343
mov  [CurrDst], eax
344
 
345
add  di, 32 - 6      ; Load first cluster number
346
mov  ax, [es:di]
347
mov  cx, ds          ; Fix `es' selector just in case
348
mov  es, cx
349
 
350
LoadKernel:
351
 
352
call LoadCluster     ; Load cluster `ax' to [CurrDst], update [CurrDst]
353
 
354
call NextCluster     ; Get next cluster number in ax
355
 
356
cmp  ax, 0FF8h       ; Repeat until EOF
357
jb   LoadKernel
358
 
359
RunKernel:
360
 
361
mov  ax, KernelSeg   ; Setup data segment and transfer control
362
mov  ds, ax
363
 
364
jmp  KernelSeg:KernelAddr  ; Huzzah!!
365
 
366
 
367
; Load cluster `ax' to [CurrDst], update [CurrDst]
368
 
369
LoadCluster:
370
 
371
push ax
372
sub  ax, 2           ; Cluster numbers start at 2
373
movzx eax, ax
374
 
375
xor  ecx, ecx        ; Calculate bytes in a cluster
376
mov  cl, [SpClst]
377
imul cx, [BpSect]
378
 
379
imul eax, ecx
380
add  eax, [BegData]  ; Start of cluster
381
 
382
shr  ecx, 2          ; Cluster size in dwords
383
mov  esi, eax        ; Copy source
384
mov  edi, [CurrDst]  ; Copy destination
385
call CopyData32
386
 
387
mov  [CurrDst], edi  ; Update dest
388
pop  ax              ; Restore cluster number
389
 
390
ret
391
 
392
; Search FAT (FAT12 format) for next cluster in file after `ax'.
393
 
394
NextCluster:
395
 
396
movzx ecx, ax        ; Calculate offset into FAT
397
shr  ax, 1
398
pushf
399
add  cx, ax
400
 
401
mov  esi, [BegFAT]   ; Copy word containing next cluster to buffer
402
add  esi, ecx
403
mov  edi, RelocBase + Buffer
404
xor  ecx, ecx
405
inc  ecx
406
call CopyData32
407
 
408
mov  ax, [Buffer]    ; Handle odd/even cluster numbers
409
popf
410
jnc  EvenCluster
411
shr  ax, 4
412
 
413
EvenCluster:
414
 
415
and  ax, 0FFFh
416
ret
417
 
418
; Enable the A20 line for accesses to extended memory.
419
 
420
EnableA20:
421
        in al,92h
422
        or al,2
423
        jmp short $+2
424
        jmp short $+2
425
        jmp short $+2
426
        out 92h,al
427
        ret
428
 
429
; The CopyData32 routine copies ecx dwords from esi to edi. Both esi
430
; and edi hold 32-bit values. CopyData32 runs in 32-bit protected mode.
431
 
432
CopyData32:
433
        cli
434
 
435
        call EnableA20   ; Put here in case file I/O screws with this
436
                         ; or with the GDTR
437
 
438
        lgdt [GDTStart]  ; Initialize GDTR for 32-bit protected mode
439
 
440
        mov eax, cr0
441
        or al, 1
442
        mov cr0, eax     ;go to real flat mode
443
 
444
;       LED_GRN
445
;       PSW_WAIT
446
 
447
        jmp  dword 8h : RelocBase+ProtJmp
448
[bits 32]
449
ProtJmp:
450
;       LED_YEL
451
;       PSW_WAIT
452
 
453
        mov ax, 10h
454
        mov ds, ax
455
        mov es, ax
456
        mov ss, ax
457
 
458
        rep movsd       ;copy the sector to where it should be
459
 
460
        mov ax, 20h
461
        mov ds, ax
462
        mov es, ax
463
        mov ss, ax
464
 
465
;       LED_RED
466
;       PSW_WAIT
467
 
468
        jmp 18h : RealJmp1  ;use code segment with 64K limit
469
[bits 16]
470
RealJmp1:
471
;       LED_OFF
472
;       PSW_WAIT
473
 
474
        mov eax, cr0      ;back to real segmented mode
475
        and eax, 0fffffffeh
476
        mov cr0, eax
477
 
478
        jmp  RelocSeg : RealJmp2
479
RealJmp2:
480
;       LED_GRN
481
;       PSW_WAIT
482
 
483
        mov ax, cs
484
        mov es, ax
485
        mov ds, ax
486
        mov ss, ax
487
 
488
        sti
489
ret
490
 
491
; Storage for a Dos 3+ BIOS Parameter Block (for the C: ramdisk)
492
 
493
SavBPB:
494
 
495
BpSect  dw  0h       ; Bytes per sector, always 512
496
SpClst  db  0h       ; Sectors per cluster
497
ResSec  dw  0h       ; Num of reserved sectors
498
NumFAT  db  0h       ; Num of FATs
499
NRoot   dw  0h       ; Num of root directory entries
500
TotSec  dw  0h       ; Total sectors
501
Media   db  0h       ; Media descriptor byte
502
SecFAT  dw  0h       ; Sectors per FAT
503
 
504
EndBPB:
505
 
506
CurrDst dd  0h       ; Current destination address for copying RTEMS exec
507
 
508
; Important (32-bit) address for the C: ramdisk
509
 
510
BegFAT  dd  0h       ; Start of the FAT
511
BegRoot dd  0h       ; Start of root directory
512
BegData dd  0h       ; Start of data clusters
513
 
514
DDrive  db  0h       ; Default drive: 0h = A:, 2h = C:
515
 
516
DirName times 11 db 32 ; Room for 8.3 directory entry name
517
 
518
FName   times 13 db 0  ; Room for a 12 character null-terminated string
519
FHndl   dw  0000h
520
 
521
Greet   db  "RTEMS DOS Loader (c) 1999 Tony R. Ambardar",13,10,"$"
522
Button  db  "Button pressed -- Aborting.",13,10,"$"
523
FError  db  "Missing or incorrect file name.",13,10,"$"
524
RError  db  "Error opening or reading file.",13,10,"$"
525
 
526
; Global Descriptor Table used for protectd mode.
527
; Store the GDTR in the first null GDT entry
528
 
529
GDTStart:
530
 
531
dw GDTEnd - GDTStart - 1
532
dd RelocBase + GDTStart
533
dw 0
534
 
535
; base=0h, limit=4Gb, present, code, exec/read, conform, 32-bit
536
 
537
dw 0ffffh   ;seg. lim. [15:0]
538
dw 0        ;base[15:0]
539
db 0        ;base[23:16]
540
db 9eh      ;p=1,dpl=0,s=1 ; code: execute/read, conforming
541
db 0cfh     ;c: gran=4K, D/B=1(32-bit) ; f: seg. lim. [19:16]
542
db 0        ;base[31:24]
543
 
544
; base=0h, limit=4Gb, present, data, read/write exp. up, 32-bit SP
545
 
546
dw 0ffffh   ;seg. lim. [15:0]
547
dw 0        ;base[15:0]
548
db 0        ;base[23:16]
549
db 92h      ;p=1,dpl=0,s=1 ; data: read/write expand-up
550
db 0cfh     ;c: gran=4K, D/B=1(32-bit) ; f: seg. lim. [19:16]
551
db 0        ;base[31:24]
552
 
553
; base=0h, limit=ffffh, present, code, exec/read, conform, 16-bit
554
; NOTE: this descriptor is used to change back to real mode.
555
 
556
dw 0ffffh   ;seg. lim. [15:0]
557
dw Reloc15  ;base[15:0]
558
db Reloc23  ;base[23:16]
559
db 9eh      ;p=1,dpl=0,s=1 ; code: execute/read, conforming
560
db 000h     ;4: gran=1 byte, D/B=0(16-bit) ; 0: seg. lim. [19:16]
561
db 0        ;base[31:24]
562
 
563
; base=0h, limit=ffffh, present, data, read/write exp. up, 16-bit SP
564
; NOTE: this descriptor is used to change back to real mode.
565
 
566
dw 0ffffh   ;seg. lim. [15:0]
567
dw Reloc15  ;base[15:0]
568
db Reloc23  ;base[23:16]
569
db 92h      ;p=1,dpl=0,s=1 ; data: read/write expand-up
570
db 000h     ;0: gran=1 byte, D/B=0(16-bit) ; 0: seg. lim. [19:16]
571
db 0        ;base[31:24]
572
 
573
GDTEnd:
574
 
575
CodeEnd:                    ; end-of-code marker for copy

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.