Chameleon

Chameleon Commit Details

Date:2015-02-27 00:20:20 (9 years 1 month ago)
Author:ErmaC
Commit:2585
Parents: 2584
Message:Merge Interrupt Management changes from Zenith432 branch to my branch
Changes:
A/branches/ErmaC/Enoch/i386/libsa/interrupts.c
M/branches/ErmaC/Enoch/CHANGES
M/branches/ErmaC/Enoch/i386/libsaio/bios.s
M/branches/ErmaC/Enoch/i386/boot2/options.c
M/branches/ErmaC/Enoch/i386/libsaio/biosfn.c
M/branches/ErmaC/Enoch/i386/libsa/Makefile
M/branches/ErmaC/Enoch/i386/boot2/boot.c
M/branches/ErmaC/Enoch/i386/boot2/gui.c
M/branches/ErmaC/Enoch/i386/libsa/libsa.h

File differences

branches/ErmaC/Enoch/i386/libsaio/bios.s
106106
107107
108108
109
110
109111
110112
111113
......
179181
180182
181183
184
182185
183186
184187
*/
LABEL(_bios)
enter $0, $0
pushfl
cli
pushal
movl 8(%ebp), %edx // address of save area
movl %ebp, O_EBP(%edx)
popal
popfl
leave
ret
branches/ErmaC/Enoch/i386/libsaio/biosfn.c
5353
5454
5555
56
5657
5758
5859
5960
6061
6162
63
64
6265
6366
6467
......
8588
8689
8790
91
8892
8993
9094
9195
96
97
98
9299
93100
94101
......
96103
97104
98105
106
99107
100108
101109
......
112120
113121
114122
123
124
125
126
115127
116128
117129
......
741753
742754
743755
756
744757
745758
746759
......
750763
751764
752765
766
753767
754768
755769
......
977991
978992
979993
994
980995
981996
982997
......
9971012
9981013
9991014
1015
10001016
10011017
10021018
1003
1004
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
10051029
10061030
10071031
int bgetc(void)
{
#if 0
/* Poll for the next character. Most real BIOS do not need this as the
INT 16h,AH=0h function will block until one is received.
Unfortunately, Apple's EFI CSM will never wake up. This idea is lifted
from the grub-a20.patch to GRUB's stage2/asm.S file.
*/
while(!readKeyboardStatus());
// Apple's EFI CSM???? Who cares - Zenith432
#endif
bb.intno = 0x16;
bb.eax.r.h = 0x00;
int readKeyboardShiftFlags(void)
{
#if 0
bb.intno = 0x16;
bb.eax.r.h = 0x02;
bios(&bb);
return bb.eax.r.l;
#else
return *(uint8_t const volatile*) 0x417U;
#endif
}
unsigned int time18(void)
{
#if 0
union {
struct {
unsigned int low:16;
time.s.high = bb.ecx.rr;
return time.i;
#else
(void) __sync_lock_test_and_set((uint8_t volatile*) 0x470U, (uint8_t) 0U);
return *(uint32_t const volatile*) 0x46CU;
#endif
}
//#if 0 /* COMMENTED */
//==============================================================================
#if UNUSED
int ebiosEjectMedia(int biosdev)
{
bb.intno = 0x13;
bios(&bb);
return bb.eax.r.h;
}
#endif
void setCursorPosition(int x, int y, int page)
{
}
#endif /* EISA_SUPPORT */
#if UNUSED
#define PCI_SIGNATURE 0x20494350 /* "PCI " */
int
}
return -1;
}
#endif
void sleep(int n)
{
unsigned int endtime = (time18() + 18*n);
while (time18() < endtime);
// FIXME: doesn't handle midnight wraparound
unsigned int endtime = (time18() + 18*n);
#ifdef __i386__
while (time18() < endtime)
{
__asm__ volatile ("rep; nop");
}
#else
while (time18() < endtime);
#endif
}
branches/ErmaC/Enoch/i386/boot2/boot.c
7777
7878
7979
80
81
8082
8183
8284
......
199201
200202
201203
204
205
206
207
202208
203209
204210
......
224230
225231
226232
233
234
235
236
237
227238
228239
229240
......
233244
234245
235246
247
248
249
250
251
236252
237253
238254
239255
240
256
241257
242258
243259
......
437453
438454
439455
456
457
458
459
460
461
462
440463
441464
442465
......
839862
840863
841864
865
866
867
868
869
842870
843871
844872
boolgScanSingleDrive;
booluseGUI;
static intinterruptsAvailable = 0;
static boolgUnloadPXEOnExit = false;
static chargCacheNameAdler[64 + 256];
usb_loop();
#if DEBUG
if (interruptsAvailable) ShowInterruptCounters();
#endif
// If we were in text mode, switch to graphics mode.
// This will draw the boot graphics unless we are in
// verbose mode.
// Notify modules that the kernel is about to be started
execute_hook("Kernel Start", (void *)kernelEntry, (void *)bootArgs, NULL, NULL);
if (interruptsAvailable)
{
DisableInterrupts();
}
// Masking out so that Lion doesn't doublefault
startprog( kernelEntry, bootArgs );
// Notify modules that the kernel is about to be started
execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgsPreLion, NULL, NULL);
if (interruptsAvailable)
{
DisableInterrupts();
}
startprog( kernelEntry, bootArgsPreLion );
}
// Not reached
return 0;
__builtin_unreachable();
}
// Initialize boot-log
initBooterLog();
// Enable interrupts
interruptsAvailable = SetupInterrupts();
if (interruptsAvailable)
{
EnableInterrupts();
}
// Initialize boot info structure.
initKernBootStruct();
{
nbpUnloadBaseCode();
}
if (interruptsAvailable)
{
DisableInterrupts();
}
}
/*!
branches/ErmaC/Enoch/i386/boot2/gui.c
19671967
19681968
19691969
1970
19701971
19711972
19721973
......
19861987
19871988
19881989
1990
19891991
19901992
19911993
......
20452047
20462048
20472049
2050
20482051
2052
20492053
20502054
20512055
// ====================================================================
#if UNUSED
void animateProgressBar()
{
int y;
pixel(buffBar, buffBar->width-1, 0).value = buff;
}
}
#endif
// ====================================================================
}
blend(&progressbar, blendInto, p);
#if 0
animateProgressBar();
#endif
free(progressbar.pixels);
}
branches/ErmaC/Enoch/i386/boot2/options.c
190190
191191
192192
193
193
194
194195
195
196
197
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
198211
199212
200213
......
207220
208221
209222
210
223
211224
212225
213226
......
413426
414427
415428
416
429
417430
418431
419432
......
451464
452465
453466
454
467
455468
456
457
458
459
460
461
462
463
464
465
469
470
471
472
473
474
475
476
477
478
466479
467
480
468481
469482
470483
471484
472485
473
486
474487
475488
476489
477
478
490
491
479492
480493
481494
482495
483496
484497
485
498
486499
487500
488501
......
490503
491504
492505
493
506
494507
495508
496509
......
518531
519532
520533
521
534
522535
523536
524537
......
528541
529542
530543
531
544
532545
533546
534547
535548
536549
537
550
538551
539552
540553
541554
542555
543
556
544557
545558
546559
547560
548561
549562
550
563
551564
552
553
554
555
565
566
567
568
569
570
556571
557572
558573
......
571586
572587
573588
574
575
576
577
578
579
589
590
591
592
593
594
580595
581
582
596
597
583598
584
585
586
587
588
589
590
599
600
601
602
603
604
605
591606
592
593
594
607
608
595609
596610
597611
598
612
599613
600614
601615
......
610624
611625
612626
613
614
615
616
627
628
629
617630
618
619
631
632
633
634
635
636
620637
621
622638
623
624
625
626
627
639
640
641
642
643
628644
629
645
646
647
648
649
650
630651
631
632
652
653
633654
634655
635
636
637
638
639656
640657
641658
......
750767
751768
752769
753
770
771
754772
755773
756774
......
760778
761779
762780
763
781
782
764783
765784
766785
......
11561175
11571176
11581177
1178
11591179
11601180
11611181
......
12001220
12011221
12021222
1223
12031224
12041225
12051226
......
12431264
12441265
12451266
1246
1247
1248
1249
1250
1251
1252
1253
1254
1267
1268
1269
1270
1271
1272
1273
1274
1275
12551276
12561277
12571278
for ( time = time18(), timeout++; timeout > 0; )
{
if( time18() > lasttime)
int currenttime;
if (lasttime)
{
multi--;
lasttime=time18();
}
currenttime = time18();
if( currenttime > lasttime)
{
multi -= (currenttime - lasttime);
if (multi < 0)
{
multi = 0;
}
lasttime=currenttime;
}
}
else
{
lasttime = currenttime = time;
}
if ( (ch = readKeyboardStatus()) )
break;
break;
}
if ( time18() >= time )
if ( currenttime >= time )
{
time += 18;
timeout--;
gMenuStart= 0;
gMenuEnd = MIN( count, gui.maxdevices ) - 1;
// If the selected item is not visible, shift the list down.
if ( gMenuSelection > gMenuBottom )
static int updateMenu( int key, void ** paramPtr )
{
int moved = 0;
int moved = 0;
union {
struct {
unsigned int
selectionUp : 1,
selectionDown : 1,
scrollUp : 1,
scrollDown : 1;
} f;
unsigned int w;
} draw = {{0}};
union {
struct {
unsigned int
selectionUp : 1,
selectionDown : 1,
scrollUp : 1,
scrollDown : 1;
} f;
unsigned int w;
} draw = {{0}};
if ( gMenuItems == NULL )
if ( gMenuItems == NULL )
return 0;
if( bootArgs->Video.v_display != VGA_TEXT_MODE )
{
int res;
// set navigation keys for horizontal layout as defaults
int previous= 0x4B00;// left arrow
int subsequent= 0x4D00;// right arrow
int menu= 0x5000;// down arrow
int menu= 0x5000;// down arrow
if ( gui.layout == VerticalLayout )
{
// set navigation keys for vertical layout
previous= 0x4800;// up arrow
subsequent= 0x5000;// down arrow
menu= 0x4B00;// right arrow
}
}
if ( key == previous )
{
draw.f.selectionUp = 1;
else if ( gMenuTop > 0 )
draw.f.scrollDown = 1;
}
else if ( key == subsequent )
else
{
shouldboot = ( res != DO_NOT_BOOT );
if ( shouldboot )
gui.menu.draw = false;
gVerboseMode = false;
gBootMode = kBootModeNormal;
break;
case BOOT_VERBOSE:
gVerboseMode = true;
gBootMode = kBootModeNormal;
addBootArg(kVerboseModeFlag);
break;
case BOOT_IGNORECACHE:
gVerboseMode = false;
gBootMode = kBootModeNormal;
addBootArg(kIgnoreCachesFlag);
break;
case BOOT_SINGLEUSER:
gVerboseMode = true;
gBootMode = kBootModeNormal;
addBootArg(kSingleUserModeFlag);
break;
}
}
}
} else {
}
}
else
{
switch ( key )
{
case 0x4800: // Up Arrow
}
}
if ( draw.w )
{
if ( draw.f.scrollUp )
{
scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, 1);
gMenuTop++; gMenuBottom++;
if ( draw.w )
{
if ( draw.f.scrollUp )
{
scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, 1);
gMenuTop++; gMenuBottom++;
gMenuStart++; gMenuEnd++;
draw.f.selectionDown = 1;
}
draw.f.selectionDown = 1;
}
if ( draw.f.scrollDown )
{
scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, -1);
gMenuTop--; gMenuBottom--;
gMenuStart--; gMenuEnd--;
draw.f.selectionUp = 1;
}
if ( draw.f.scrollDown )
{
scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, -1);
gMenuTop--; gMenuBottom--;
gMenuStart--; gMenuEnd--;
draw.f.selectionUp = 1;
}
if ( draw.f.selectionUp || draw.f.selectionDown )
{
if ( draw.f.selectionUp || draw.f.selectionDown )
{
CursorState cursorState;
// Set cursor at current position, and clear inverse video.
if( bootArgs->Video.v_display == VGA_TEXT_MODE )
{
changeCursor( 0, gMenuRow + gMenuSelection - gMenuTop, kCursorTypeHidden, &cursorState );
gMenuStart--;
gMenuEnd--;
}
} else {
gMenuSelection++;
if(( gMenuSelection - ( gui.maxdevices - 1) - gMenuStart) > 0 )
}
else
{
gMenuStart++;
gMenuEnd++;
gMenuSelection++;
if(( gMenuSelection - ( gui.maxdevices - 1) - gMenuStart) > 0 )
{
gMenuStart++;
gMenuEnd++;
}
}
}
if( bootArgs->Video.v_display == VGA_TEXT_MODE )
{
moveCursor( 0, gMenuRow + gMenuSelection - gMenuTop );
printMenuItem( &gMenuItems[gMenuSelection], 1 );
restoreCursor( &cursorState );
if( bootArgs->Video.v_display == VGA_TEXT_MODE )
{
moveCursor( 0, gMenuRow + gMenuSelection - gMenuTop );
printMenuItem( &gMenuItems[gMenuSelection], 1 );
restoreCursor( &cursorState );
} else
}
else
{
drawDeviceList (gMenuStart, gMenuEnd, gMenuSelection);
}
}
drawDeviceList (gMenuStart, gMenuEnd, gMenuSelection);
*paramPtr = gMenuItems[gMenuSelection].param;
moved = 1;
}
*paramPtr = gMenuItems[gMenuSelection].param;
moved = 1;
}
return moved;
}
void lspci(void)
{
if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
if (bootArgs->Video.v_display == VGA_TEXT_MODE)
{
setActiveDisplayPage(1);
clearScreenRows(0, 24);
setCursorPosition(0, 0, 1);
pause();
if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
if (bootArgs->Video.v_display == VGA_TEXT_MODE)
{
setActiveDisplayPage(0);
}
}
clearScreenRows(kMenuTopRow, kScreenLastRow);
changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
}
shouldboot = false;
gui.menu.draw = false;
if (menuItems) {
*argP += cnt;
*argP[0] = ' ';
(*argP)++;
*cntRemainingP -= len;
return true;
int processBootOptions()
{
const char *cp = gBootArgs;
const char *val = 0;
const char *kernel;
int cnt;
int userCnt;
int cntRemaining;
char *argP;
char *configKernelFlags;
char *valueBuffer;
const char*cp = gBootArgs;
const char*val = 0;
const char*kernel;
intcnt;
intuserCnt;
intcntRemaining;
char*argP;
char*configKernelFlags;
char*valueBuffer;
valueBuffer = malloc(VALUE_SIZE);
branches/ErmaC/Enoch/i386/libsa/interrupts.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
#ifdef __i386__
#include "libsa.h"
#include "saio_internal.h"
#ifdef DEBUG_INTERRUPTS
#define DBG(x...) printf(x)
#else
#define DBG(x...)
#endif
#define CODE_SEGMENT_SELECTOR 0x28U
#define CODED_EXCEPTION_MASK 0x27D00U
#define IA32_APIC_BASE 27U
#define IA32_APIC_BASE_BSP 0x100U
#define IA32_APIC_BASE_EN 0x800U
#define LAPIC_WANTED_FLAGS (IA32_APIC_BASE_EN | IA32_APIC_BASE_BSP)
#define LAPIC_EOI_OFFSET 0xB0U
#define LAPIC_ISR_OFFSET 0x100U
#define PIC_READ_ISR_COMMAND 11U
#define PIC_EOI_COMMAND 0x20U
#define PIC_PORT0 0
#define PIC_PORT1 1
#define BDA_TICK_COUNT 0x46CU// DWORD
#define BDA_MIDNIGHT_FLAG 0x470U// BYTE
#define BDA_24HR_TURNOVER 0x1800B0U
enum InterruptSources
{
IS_Unknown = 0,
IS_APIC = 1,// Covers both LAPIC and IOAPIC
IS_PIC0 = 2,
IS_PIC1 = 3,
IS_Software = 4
};
struct InterruptFrame
{
uint32_t edx;
uint32_t ecx;
uint32_t eax;
uint32_t index;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
};
struct ExceptionFrame
{
uint32_t edi;
uint32_t esi;
uint32_t ebp;
uint32_t esp;
uint32_t ebx;
uint32_t edx;
uint32_t ecx;
uint32_t eax;
uint32_t index;
uint32_t exception_code;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
};
struct InterruptGate
{
uint16_t offset_0_15;
uint16_t selector;
uint16_t flags;
uint16_t offset_16_31;
};
#pragma mark -
#pragma mark Global Data
#pragma mark -
extern
uint16_t Idtr_prot[];
static
uint32_t* counters = NULL;
static
uint32_t lapic_base = 0U;
static
uint8_t const PicPorts[2][2] = { { 0x20U, 0x21U }, { 0xA0U, 0xA1U } };
#pragma mark -
#pragma mark Assembly Stubs
#pragma mark -
static
__attribute__((naked, noreturn))
void InterruptStub(void)
{
__asm__ volatile ("pushl %%eax\n\t"
"pushl %%ecx\n\t"
"pushl %%edx\n\t"
"pushl %%esp\n\t"
"calll _InterruptHandler\n\t"
"addl $4, %%esp\n\t"
"popl %%edx\n\t"
"popl %%ecx\n\t"
"popl %%eax\n\t"
"addl $4, %%esp\n\t"
"iretl"
:);
}
static
__attribute__((naked, noreturn))
void ExceptionWithCodeStub(void)
{
__asm__ volatile("testl $-57, 8(%%esp)\n\t"
"je 0f\n\t"
"pushal\n\t"
"jmp 1f\n"
"_ExceptionNoCodeStub:\n"
"0:\tsub $4, %%esp\n\t"
"pushal\n\t"
"xorl %%eax, %%eax\n\t"
"xchgl %%eax, 36(%%esp)\n\t"
"movl %%eax, 32(%%esp)\n"
"1:\taddl $20, 12(%%esp)\n\t"
"pushl %%esp\n\t"
"calll _ExceptionHandler\n\t"
"addl $4, %%esp\n\t"
"popal\n\t"
"addl $8, %%esp\n\t"
"iretl"
:);
}
/*
* Make _ExceptionNoCodeStub accessible to C
*/
static
__attribute__((naked, noreturn, weakref("ExceptionNoCodeStub")))
void ExceptionNoCodeStubAlias(void);
static
__attribute__((/* naked, */noinline, regparm(1), section("__INIT,__text")))
void DispatchBiosVector(uint8_t vector)
{
__asm__ volatile ("movb %0, 0f + 1\n\t"
"calll __prot_to_real\n\t"
".code16\n"
"0:\tint $0\n\t"
"calll __real_to_prot\n\t"
".code32"
: : "r"(vector));
}
static
__attribute__((noreturn, noinline, section("__INIT,__text")))
void DisplayErrorAndStop(void)
{
__asm__ volatile ("calll __prot_to_real\n\t"
".code16\n\t"
"movw $2, %%ax\n\t"
"int $0x10\n\t"
"xorw %%ax, %%ax\n\t"
"movw %%ax, %%ds\n\t"
"movw $0x6000, %%si\n\t"
"cld\n"
"0:\tlodsb\n\t"
"testb %%al, %%al\n\t"
"je 1f\n\t"
"movb $0xE, %%ah\n\t"
"movw $0xFF, %%bx\n\t"
"int $0x10\n\t"
"jmp 0b\n"
"1:\thlt\n\t"
"jmp 1b\n\t"
".code32"
:);
__builtin_unreachable();
}
#pragma mark -
#pragma mark Other Inline Assembly
#pragma mark -
static inline
uint32_t ReadLapic(uint32_t offset)
{
return *(uint32_t const volatile*) (lapic_base + offset);
}
static inline
void WriteLapic(uint32_t offset, uint32_t value)
{
*(uint32_t volatile*) (lapic_base + offset) = value;
}
static inline
uint8_t ReadPic(int pic, int index)
{
uint8_t value;
__asm__ volatile ("inb %1, %0" : "=a"(value) : "N"(PicPorts[pic][index]));
return value;
}
static inline
void WritePic(int pic, int index, uint8_t value)
{
__asm__ volatile ("outb %0, %1" : : "a"(value), "N"(PicPorts[pic][index]));
}
#pragma mark -
#pragma mark Main Code
#pragma mark -
static
int IdentifyInterruptSource(uint8_t vector, uint32_t eip)
{
if (lapic_base)
{
uint32_t value = ReadLapic(LAPIC_ISR_OFFSET + ((vector & 0xE0U) >> 1));
if (value & (1U << (vector & 31U)))
return IS_APIC;
}
if (vector >= 8U && vector < 16U)
{
uint8_t value;
WritePic(0, PIC_PORT0, PIC_READ_ISR_COMMAND);
value = ReadPic(0, PIC_PORT0);
if (value & (1U << (vector & 7U)))
return IS_PIC0;
}
if (vector >= 0x70U && vector < 0x78U)
{
uint8_t value;
WritePic(1, PIC_PORT0, PIC_READ_ISR_COMMAND);
value = ReadPic(1, PIC_PORT0);
if (value & (1U << (vector & 7U)))
return IS_PIC1;
}
if (eip)
{
uint8_t const volatile* pInstruction = (uint8_t const volatile*) (eip - 2U);
if ((*pInstruction) == 0xCDU && pInstruction[1] == vector)
return IS_Software;
/*
* There are other software interrupt opcodes
* debug breakpoint 0xCC
* interrupt on overflow 0xCE
* bound instruction 0x62
* but those all trigger specific vectors, so are handled as exceptions.
*/
}
return IS_Unknown;
}
static
void SignalEOI(int source)
{
switch (source)
{
case IS_APIC:
if (lapic_base)
WriteLapic(LAPIC_EOI_OFFSET, 0U);
break;
case IS_PIC1:
WritePic(1, PIC_PORT0, PIC_EOI_COMMAND);
case IS_PIC0:
WritePic(0, PIC_PORT0, PIC_EOI_COMMAND);
default:
break;
}
}
static
void HandleIRQ(int source, uint8_t vector)
{
if (source == IS_PIC0 && vector == 8U)
{
uint32_t* pTickCount = (uint32_t*) BDA_TICK_COUNT;
if (++(*pTickCount) == BDA_24HR_TURNOVER)
{
*pTickCount = 0U;
++(*(uint8_t*)BDA_MIDNIGHT_FLAG);
}
SignalEOI(source);
return;
}
/*
* Default Approach: send to bios
*/
DispatchBiosVector(vector);
}
static
__attribute__((used))
void ExceptionHandler(struct ExceptionFrame* pFrame)
{
uint8_t vector;
int interruptSource;
char* errorString;
/*
* FIXME: Should check if 0x10000U <= ESP <= 0x1FFFF0 here and switch stacks if not.
*/
if (!pFrame)
{
return;
}
vector = (uint8_t) pFrame->index;
if (counters)
++counters[vector];
interruptSource = IdentifyInterruptSource(vector, pFrame->eip);
switch (interruptSource)
{
case IS_APIC:
case IS_PIC0:
case IS_PIC1:
HandleIRQ(interruptSource, vector);
case IS_Software:
return;
default:
break;
}
errorString = (char*) 0x6000U;
switch (vector)
{
case 0U:
strcpy(errorString, "Division By Zero Exception");
break;
case 1U:
strcpy(errorString, "Debug Exception");
break;
case 2U:
strcpy(errorString, "NMI Interrupt");
break;
case 3U:
strcpy(errorString, "Debug Breakpoint");
break;
case 4U:
strcpy(errorString, "Overflow Exception");
break;
case 5U:
strcpy(errorString, "BOUND Range Exception");
break;
case 6U:
strcpy(errorString, "Invalid Opcode Exception");
break;
case 7U:
strcpy(errorString, "Math Coprocessor Unavailable Exception");
break;
case 8U:
strcpy(errorString, "Double Fault");
break;
case 9U:
strcpy(errorString, "Coprocessor Segment Overrun Exception");
break;
case 10U:
strcpy(errorString, "Invalid TSS Exception");
break;
case 11U:
strcpy(errorString, "Segment Not Present Exception");
break;
case 12U:
strcpy(errorString, "Stack-Segment Fault");
break;
case 13U:
strcpy(errorString, "General Protection Fault");
break;
case 14U:
strcpy(errorString, "Page Fault");
break;
case 16U:
strcpy(errorString, "x87 FPU Floating-Point Error");
break;
case 17U:
strcpy(errorString, "Alignment Check Exception");
break;
case 18U:
strcpy(errorString, "Machine Check Exception");
break;
case 19U:
strcpy(errorString, "SIMD Floating-Point Exception");
break;
case 20U:
strcpy(errorString, "Virtualization Exception");
break;
default:
sprintf(errorString, "Unknown Exception Vector %d", (int) vector);
break;
}
errorString += strlen(errorString);
errorString += sprintf(errorString, "\r\nEDI 0x%x, ESI 0x%x, EBP 0x%x, ESP 0x%x",
pFrame->edi, pFrame->esi, pFrame->ebp, pFrame->esp);
errorString += sprintf(errorString, "\r\nEBX 0x%x, EDX 0x%x, ECX 0x%x, EAX 0x%x",
pFrame->ebx, pFrame->edx, pFrame->ecx, pFrame->eax);
errorString += sprintf(errorString, "\r\nException Code 0x%x, EIP 0x%x, CS 0x%x, EFLAGS 0x%x\r\nSystem Halted\r\n",
pFrame->exception_code, pFrame->eip, pFrame->cs, pFrame->eflags);
DisplayErrorAndStop();
}
static
__attribute__((used))
void InterruptHandler(struct InterruptFrame* pFrame)
{
uint8_t vector;
int interruptSource;
if (!pFrame)
{
return;
}
vector = (uint8_t) pFrame->index;
if (counters)
++counters[vector];
interruptSource = IdentifyInterruptSource(vector, pFrame->eip);
switch (interruptSource)
{
case IS_APIC:
case IS_PIC0:
case IS_PIC1:
HandleIRQ(interruptSource, vector);
default:
break;
}
}
#if UNUSED
void dumpMasks(void)
{
int idx;
uint8_t port_val;
uint8_t volatile* apic_index;
uint32_t const volatile* apic_data;
port_val = ReadPic(0, 1);
DBG("pic0 Masks 0x%x\n", port_val);
port_val = ReadPic(1, 1);
DBG("pic1 Masks 0x%x\n", port_val);
getchar();
DBG("IOAPIC vectors\n");
apic_index = (uint8_t volatile*) 0xFEC00000U;
apic_data = (uint32_t const volatile*) 0xFEC00010U;
for (idx = 0; idx != 24; ++idx)
{
uint32_t v1, v2;
*apic_index = (uint8_t) (16U + 2U * (unsigned) idx);
v1 = *apic_data;
if (v1 & 0x10000U)
continue;
*apic_index = (uint8_t) (16U + 2U * (unsigned) idx + 1U);
v2 = *apic_data;
DBG("index %d vector 0x%x%08x\n", idx, v2, v1);
}
getchar();
if (!lapic_base)
return;
DBG("LAPIC vectors\n");
for (idx = 0; idx != 7; ++idx)
{
uint32_t offs, v;
if (!idx)
offs = 0x2F0U;
else
offs = 0x320U + 16U * (unsigned) (idx - 1);
v = ReadLapic(offs);
if (v & 0x10000U)
continue;
DBG("index %d vector 0x%x\n", idx, v);
}
}
#endif
void ShowInterruptCounters(void)
{
int j;
if (!counters)
return;
msglog("Interrupt Counters\n");
for (j = 0; j != 256; ++j)
if (counters[j])
msglog("counters[%d] == %d\n", j, counters[j]);
}
int SetupInterrupts(void)
{
int idx;
uint32_t stub_address;
uint64_t ia32_apic_base;
size_t const total = 2048U + 2048U + 1024U;
uint8_t* workArea = (uint8_t*) malloc(total);
if (!workArea)
{
msglog("%s: Memory Allocation Failed\n", __FUNCTION__);
return 0;
}
counters = (uint32_t*) (workArea + 4096);
bzero(counters, 1024U);
for (idx = 0; idx != 256; ++idx)
{
struct InterruptGate* gate = (struct InterruptGate*) (workArea + idx * sizeof(struct InterruptGate));
uint8_t* thunk = workArea + 2048 + idx * 8;
gate->offset_0_15 = ((uint32_t) thunk) & 0xFFFFU;
gate->selector = CODE_SEGMENT_SELECTOR;
gate->flags = 0x8E00U; // Interrupt Gate, Present, DPL 0, 32-bit
gate->offset_16_31 = (((uint32_t) thunk) >> 16) & 0xFFFFU;
thunk[0] = 0x6AU;// push byte
thunk[1] = (uint8_t) idx;
thunk[2] = 0xE9U;// jmp rel32
if (idx >= 32)
stub_address = (uint32_t) &InterruptStub;
else if ((1U << idx) & CODED_EXCEPTION_MASK)
stub_address = (uint32_t) &ExceptionWithCodeStub;
else
stub_address = (uint32_t) &ExceptionNoCodeStubAlias;
*(uint32_t*) (&thunk[3]) = stub_address - (uint32_t) &thunk[7];
thunk[7] = 0x90U;// nop
}
Idtr_prot[0] = 0x7FFU;
Idtr_prot[1] = ((uint32_t) workArea) & 0xFFFFU;
Idtr_prot[2] = (((uint32_t) workArea) >> 16) & 0xFFFFU;
__asm__ volatile ("lidt %0" : : "m"(Idtr_prot[0]));
__asm__ volatile ("rdmsr" : "=A"(ia32_apic_base) : "c"((uint32_t) IA32_APIC_BASE));
if ((ia32_apic_base & LAPIC_WANTED_FLAGS) == LAPIC_WANTED_FLAGS &&
!((ia32_apic_base >> 32) & 255U))
lapic_base = ((uint32_t) ia32_apic_base) & ~0xFFFU;
DBG("%s: Work Area 0x%x, lapic_base 0x%x\n", __FUNCTION__, (uint32_t) workArea, lapic_base);
return 1;
}
#endif
branches/ErmaC/Enoch/i386/libsa/libsa.h
155155
156156
157157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
158173
*/
extern struct segment_command * getsegbynamefromheader(struct mach_header * mhp, char * segname);
/*
* interrupts.c
*/
#ifdef __i386__
extern int SetupInterrupts(void);
static inline void EnableInterrupts(void) { __asm__ volatile ("sti"); }
static inline void DisableInterrupts(void) { __asm__ volatile ("cli"); }
extern void ShowInterruptCounters(void);
#else
static inline int SetupInterrupts(void) { return 0; }
static inline void EnableInterrupts(void) { }
static inline void DisableInterrupts(void) { }
static inline void ShowInterruptCounters(void) { }
#endif
#endif /* !__BOOT_LIBSA_H */
branches/ErmaC/Enoch/i386/libsa/Makefile
2323
2424
2525
26
26
2727
2828
2929
OBJS = prf.o printf.o zalloc.o \
string.o strtol.o error.o \
setjmp.o qsort.o efi_tables.o
setjmp.o qsort.o efi_tables.o interrupts.o
OBJS := $(addprefix $(OBJROOT)/, $(OBJS))
branches/ErmaC/Enoch/CHANGES
1
12
23
34
- Zenith432 : Interrupt Management
- Bungo : Added ability to auto-select last booted partition as the boot volume.
- Bungo : Added MacOSVerCurrent and MacOSVer2Int function to use instead of macros.
- Bungo : Fixed bug in gDarwinBuildVerStr extracting.

Archive Download the corresponding diff file

Revision: 2585