1 /*--------------------------------------------------------------------
\r
2 Copyright(c) 2015 Intel Corporation. All rights reserved.
\r
4 Redistribution and use in source and binary forms, with or without
\r
5 modification, are permitted provided that the following conditions
\r
8 * Redistributions of source code must retain the above copyright
\r
9 notice, this list of conditions and the following disclaimer.
\r
10 * Redistributions in binary form must reproduce the above copyright
\r
11 notice, this list of conditions and the following disclaimer in
\r
12 the documentation and/or other materials provided with the
\r
14 * Neither the name of Intel Corporation nor the names of its
\r
15 contributors may be used to endorse or promote products derived
\r
16 from this software without specific prior written permission.
\r
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
\r
19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
\r
20 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
\r
21 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
\r
22 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
\r
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
24 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
\r
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
\r
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
\r
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
29 --------------------------------------------------------------------*/
\r
31 /*-----------------------------------------------------------------------
\r
32 * Any required includes
\r
33 *------------------------------------------------------------------------
\r
35 #include "multiboot.h"
\r
36 #include "galileo_support.h"
\r
38 /*-----------------------------------------------------------------------
\r
39 * Any required local definitions
\r
40 *------------------------------------------------------------------------
\r
43 #define NULL (void *)0
\r
46 #define MUTEX_WAIT_TIME (( TickType_t ) 8 )
\r
48 /*-----------------------------------------------------------------------
\r
49 * Function prototypes
\r
50 *------------------------------------------------------------------------
\r
52 extern void *memcpy( void *pvDest, const void *pvSource, unsigned long ulBytes );
\r
54 /*-----------------------------------------------------------------------
\r
56 *------------------------------------------------------------------------
\r
58 uint32_t bootinfo = 1UL;
\r
59 uint32_t bootsign = 1UL;
\r
61 /*-----------------------------------------------------------------------
\r
63 *------------------------------------------------------------------------
\r
65 static uint32_t bGalileoSerialPortInitialized = FALSE;
\r
66 static uint32_t uiLEDBlinkState = LED_OFF;
\r
67 static uint16_t usIRQMask = 0xfffb;
\r
68 static uint32_t UART_PCI_Base = 0UL;
\r
69 static uint32_t UART_MMIO_Base = 0UL;
\r
70 static SemaphoreHandle_t semPrintfGate = 0;
\r
72 /*------------------------------------------------------------------------
\r
73 * GDT default entries (used in GDT setup code)
\r
74 *------------------------------------------------------------------------
\r
76 static struct sd gdt_default[NGDE] =
\r
78 /* sd_lolimit sd_lobase sd_midbase sd_access sd_hilim_fl sd_hibase */
\r
79 /* 0th entry NULL */
\r
80 { 0, 0, 0, 0, 0, 0, },
\r
81 /* 1st, Kernel Code Segment */
\r
82 { 0xffff, 0, 0, 0x9a, 0xcf, 0, },
\r
83 /* 2nd, Kernel Data Segment */
\r
84 { 0xffff, 0, 0, 0x92, 0xcf, 0, },
\r
85 /* 3rd, Kernel Stack Segment */
\r
86 { 0xffff, 0, 0, 0x92, 0xcf, 0, },
\r
87 /* 4st, Boot Code Segment */
\r
88 { 0xffff, 0, 0, 0x9a, 0xcf, 0, },
\r
89 /* 5th, Code Segment for BIOS32 request */
\r
90 { 0xffff, 0, 0, 0x9a, 0xcf, 0, },
\r
91 /* 6th, Data Segment for BIOS32 request */
\r
92 { 0xffff, 0, 0, 0x92, 0xcf, 0, },
\r
95 extern struct sd gdt[]; /* Global segment table (defined in startup.S) */
\r
97 /*------------------------------------------------------------------------
\r
98 * Set segment registers (used in GDT setup code)
\r
99 *------------------------------------------------------------------------
\r
103 extern int __text_end;
\r
105 uint32_t np, ds_end;
\r
107 ds_end = 0xffffffff/PAGE_SIZE; /* End page number */
\r
109 psd = &gdt_default[1]; /* Kernel code segment */
\r
110 np = ((int)&__text_end - 0 + PAGE_SIZE-1) / PAGE_SIZE; /* Number of code pages */
\r
111 psd->sd_lolimit = np;
\r
112 psd->sd_hilim_fl = FLAGS_SETTINGS | ((np >> 16) & 0xff);
\r
114 psd = &gdt_default[2]; /* Kernel data segment */
\r
115 psd->sd_lolimit = ds_end;
\r
116 psd->sd_hilim_fl = FLAGS_SETTINGS | ((ds_end >> 16) & 0xff);
\r
118 psd = &gdt_default[3]; /* Kernel stack segment */
\r
119 psd->sd_lolimit = ds_end;
\r
120 psd->sd_hilim_fl = FLAGS_SETTINGS | ((ds_end >> 16) & 0xff);
\r
122 psd = &gdt_default[4]; /* Boot code segment */
\r
123 psd->sd_lolimit = ds_end;
\r
124 psd->sd_hilim_fl = FLAGS_SETTINGS | ((ds_end >> 16) & 0xff);
\r
126 memcpy(gdt, gdt_default, sizeof(gdt_default));
\r
128 /*-----------------------------------------------------------*/
\r
130 /*-----------------------------------------------------------------------
\r
131 * Debug serial port display update functions
\r
132 *------------------------------------------------------------------------
\r
134 static void vCreatePrintfSemaphore( void )
\r
136 if (semPrintfGate == 0)
\r
138 semPrintfGate = xSemaphoreCreateRecursiveMutex();
\r
139 vQueueAddToRegistry( ( QueueHandle_t ) semPrintfGate, "g_printf_Mutex" );
\r
142 /*-----------------------------------------------------------*/
\r
144 void ClearScreen(void)
\r
146 g_printf(ANSI_CLEAR_SB);
\r
147 g_printf(ANSI_CLEAR_SCREEN);
\r
149 /*-----------------------------------------------------------*/
\r
151 void MoveToScreenPosition(uint8_t row, uint8_t col)
\r
153 g_printf("%c[%d;%dH", (char) 0x1B, row, col);
\r
155 /*-----------------------------------------------------------*/
\r
157 void UngatedMoveToScreenPosition(uint8_t row, uint8_t col)
\r
159 printf("%c[%d;%dH", (char) 0x1B, row, col);
\r
161 /*-----------------------------------------------------------*/
\r
163 void SetScreenColor(const char *color)
\r
165 g_printf("%s", color);
\r
167 /*-----------------------------------------------------------*/
\r
169 void g_printf(const char *format, ...)
\r
172 if (semPrintfGate == 0)
\r
173 vCreatePrintfSemaphore();
\r
175 if (xSemaphoreTakeRecursive(semPrintfGate, MUTEX_WAIT_TIME))
\r
178 va_start(arguments,format);
\r
179 print(0, format, arguments);
\r
180 xSemaphoreGiveRecursive(semPrintfGate);
\r
183 /*-----------------------------------------------------------*/
\r
185 void g_printf_rcc(uint8_t row, uint8_t col, const char *color, const char *format, ...)
\r
187 if (semPrintfGate == 0)
\r
188 vCreatePrintfSemaphore();
\r
190 if (xSemaphoreTakeRecursive(semPrintfGate, MUTEX_WAIT_TIME ))
\r
192 UngatedMoveToScreenPosition(row, col);
\r
193 printf("%s",color);
\r
195 va_start(arguments,format);
\r
196 print(0, format, arguments);
\r
197 xSemaphoreGiveRecursive(semPrintfGate);
\r
200 /*-----------------------------------------------------------*/
\r
202 void vPrintBanner( void )
\r
204 if (bGalileoSerialPortInitialized)
\r
206 /* Print an RTOSDemo Loaded message */
\r
208 g_printf_rcc(1, 2, DEFAULT_BANNER_COLOR,
\r
209 "%c[1mHELLO from the multiboot compliant FreeRTOS kernel!%c[0m",
\r
210 (char) 0x1B, (char) 0x1B );
\r
211 printf(ANSI_HIDE_CURSOR);
\r
214 /*-----------------------------------------------------------*/
\r
216 /*------------------------------------------------------------------------
\r
217 * Multiboot support (show parameters passed back from GRUB)
\r
218 *------------------------------------------------------------------------
\r
220 void show_kernel_parameters( unsigned long magic, unsigned long addr )
\r
222 /* Set to 0 to quiet display. */
\r
223 uint8_t print_values = 1;
\r
225 /* Initialise serial port if necessary. */
\r
226 vInitializeGalileoSerialPort(DEBUG_SERIAL_PORT);
\r
228 if (print_values != 0)
\r
231 g_printf(DEFAULT_SCREEN_COLOR);
\r
232 MoveToScreenPosition(1, 2);
\r
233 g_printf ("\n\r ...MULTIBOOT VALUES RETURNED FROM GRUB...\n\n\r");
\r
234 g_printf(ANSI_COLOR_WHITE);
\r
237 if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
\r
239 printf(ANSI_COLOR_RED);
\r
240 if (print_values != 0)
\r
241 g_printf (" Invalid magic number returned: 0x%08x\n\r", (unsigned) magic);
\r
242 g_printf(ANSI_COLOR_RESET);
\r
246 multiboot_info_t *mbi;
\r
247 /* Set MBI to the address of the Multiboot information structure. */
\r
248 mbi = (multiboot_info_t *) addr;
\r
250 /* Is the command line passed? */
\r
251 if (CHECK_FLAG (mbi->flags, 2))
\r
252 if (print_values != 0)
\r
253 g_printf (" cmdline = %s\n\r", (char *) mbi->cmdline);
\r
255 /* Print out the flags. */
\r
256 if (print_values != 0)
\r
257 g_printf (" flags = 0x%08x\n\r", (unsigned) mbi->flags);
\r
259 /* Are mem_* valid? */
\r
260 if (CHECK_FLAG (mbi->flags, 0))
\r
261 if (print_values != 0)
\r
262 g_printf (" mem_lower = %u KB, mem_upper = %u KB\n\r",
\r
263 (unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper);
\r
265 /* Is boot_device valid? */
\r
266 if (CHECK_FLAG (mbi->flags, 1))
\r
267 if (print_values != 0)
\r
268 g_printf (" boot_device = 0x%08x\n\r", (unsigned) mbi->boot_device);
\r
270 if (CHECK_FLAG (mbi->flags, 3))
\r
274 if (print_values != 0)
\r
275 g_printf (" mods_count = %d, mods_addr = 0x%08x\n\r",
\r
276 (int) mbi->mods_count, (int) mbi->mods_addr);
\r
277 for (i = 0, mod = (module_t *) mbi->mods_addr;
\r
278 i < (int)mbi->mods_count;
\r
281 if (print_values != 0)
\r
282 g_printf (" mod_start = 0x%08x, mod_end = 0x%08x, cmdline = %s\n\r",
\r
283 (unsigned) mod->mod_start,
\r
284 (unsigned) mod->mod_end,
\r
285 (char *) mod->string);
\r
289 /* Bits 4 and 5 are mutually exclusive! */
\r
290 if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
\r
292 if (print_values != 0)
\r
293 g_printf (" Both bits 4 and 5 are set.\n\r");
\r
297 /* Is the symbol table of a.out valid? */
\r
298 if (CHECK_FLAG (mbi->flags, 4))
\r
300 aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym);
\r
301 if (print_values != 0)
\r
302 g_printf (" multiboot_aout_symbol_table: tabsize = 0x%08x, "
\r
303 "strsize = 0x%08x, addr = 0x%08x\n\r",
\r
304 (unsigned) multiboot_aout_sym->tabsize,
\r
305 (unsigned) multiboot_aout_sym->strsize,
\r
306 (unsigned) multiboot_aout_sym->addr);
\r
309 /* Is the section header table of ELF valid? */
\r
310 if (CHECK_FLAG (mbi->flags, 5))
\r
312 elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec);
\r
313 if (print_values != 0)
\r
314 g_printf (" multiboot_elf_sec: num = %u, size = 0x%08x,"
\r
315 " addr = 0x%08x, shndx = 0x%04x\n\r",
\r
316 (unsigned) multiboot_elf_sec->num, (unsigned) multiboot_elf_sec->size,
\r
317 (unsigned) multiboot_elf_sec->addr, (unsigned) multiboot_elf_sec->shndx);
\r
320 /* Are mmap_* valid? */
\r
321 if (CHECK_FLAG (mbi->flags, 6))
\r
323 memory_map_t *mmap;
\r
324 if (print_values != 0)
\r
325 g_printf (" mmap_addr = 0x%08x, mmap_length = 0x%08x\n\r",
\r
326 (unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length);
\r
327 for (mmap = (memory_map_t *) mbi->mmap_addr;
\r
328 (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
\r
329 mmap = (memory_map_t *) ((unsigned long) mmap
\r
330 + mmap->size + sizeof (mmap->size)))
\r
332 if (print_values != 0)
\r
333 g_printf (" size = 0x%08x, base_addr = 0x%04x%04x,"
\r
334 " length = 0x%04x%04x, type = 0x%04x\n\r",
\r
335 (unsigned) mmap->size,
\r
336 (uint16_t) mmap->base_addr_high,
\r
337 (uint16_t)mmap->base_addr_low,
\r
338 (uint16_t)mmap->length_high,
\r
339 (uint16_t)mmap->length_low,
\r
340 (unsigned) mmap->type);
\r
344 if (print_values != 0)
\r
346 g_printf(DEFAULT_SCREEN_COLOR);
\r
347 g_printf ("\n\r Press any key to continue.\n\r");
\r
348 while (ucGalileoGetchar() == 0)
\r
350 __asm volatile( "NOP" );
\r
357 /*-----------------------------------------------------------*/
\r
359 /*------------------------------------------------------------------------
\r
360 * 8259 PIC initialization and support code
\r
361 *------------------------------------------------------------------------
\r
363 void vInitialize8259Chips(void)
\r
365 /* Set interrupt mask */
\r
366 uint16_t IRQMask = 0xffff;
\r
367 outb(IMR1, (uint8_t) (IRQMask & 0xff));
\r
368 outb(IMR2, (uint8_t) ((IRQMask >> 8) & 0xff));
\r
370 /* Initialise the 8259A interrupt controllers */
\r
372 /* Master device */
\r
373 outb(ICU1, 0x11); /* ICW1: icw4 needed */
\r
374 outb(ICU1+1, 0x20); /* ICW2: base ivec 32 */
\r
375 outb(ICU1+1, 0x4); /* ICW3: cascade on irq2 */
\r
376 outb(ICU1+1, 0x1); /* ICW4: buf. master, 808x mode */
\r
379 outb(ICU2, 0x11); /* ICW1: icw4 needed */
\r
380 outb(ICU2+1, 0x28); /* ICW2: base ivec 40 */
\r
381 outb(ICU2+1, 0x2); /* ICW3: slave on irq2 */
\r
382 outb(ICU2+1, 0xb); /* ICW4: buf. slave, 808x mode */
\r
384 vMicroSecondDelay (100);
\r
386 /* always read ISR */
\r
387 outb(ICU1, 0xb); /* OCW3: set ISR on read */
\r
388 outb(ICU2, 0xb); /* OCW3: set ISR on read */
\r
390 /* Set interrupt mask - leave bit 2 enabled for IC cascade */
\r
392 outb(IMR1, (uint8_t) (IRQMask & 0xff));
\r
393 outb(IMR2, (uint8_t) ((IRQMask >> 8) & 0xff));
\r
395 /*-----------------------------------------------------------*/
\r
397 void vClearIRQMask(uint8_t IRQNumber)
\r
399 if( ( IRQNumber > 31 ) && ( IRQNumber < 48 ) )
\r
401 usIRQMask &= ~( 1 << (IRQNumber - 32 ) );
\r
402 usIRQMask &= 0xfffb; // bit 2 is slave cascade
\r
403 usIRQMask |= 0x0200; // bit 14 is reserved
\r
404 outb(IMR1, (uint8_t) (usIRQMask & 0xff));
\r
405 outb(IMR2, (uint8_t) ((usIRQMask >> 8) & 0xff));
\r
408 /*-----------------------------------------------------------*/
\r
410 void vSetIRQMask(uint8_t IRQNumber)
\r
412 if( ( IRQNumber > 31 ) && ( IRQNumber < 48 ) )
\r
414 usIRQMask |= ( 1 << (IRQNumber - 32 ) );
\r
415 usIRQMask &= 0xfffb; // bit 2 is slave cascade
\r
416 usIRQMask |= 0x0200; // bit 14 is reserved
\r
417 outb(IMR1, (uint8_t) (usIRQMask & 0xff));
\r
418 outb(IMR2, (uint8_t) ((usIRQMask >> 8) & 0xff));
\r
421 /*-----------------------------------------------------------*/
\r
423 /*-----------------------------------------------------------------------
\r
424 * 82C54 PIT (programmable interval timer) initialization
\r
425 *------------------------------------------------------------------------
\r
427 void vInitializePIT(void)
\r
429 /* Set the hardware clock: timer 0, 16-bit counter, rate */
\r
430 /* generator mode, and counter runs in binary */
\r
431 outb(CLKCNTL, 0x34);
\r
433 /* Set the clock rate to 1.193 Mhz, this is 1 ms interrupt rate */
\r
434 uint16_t intrate = 1193;
\r
435 /* Must write LSB first, then MSB */
\r
436 outb(CLKBASE, (char) (intrate & 0xff));
\r
437 outb(CLKBASE, (char) ((intrate >> 8) & 0xff));
\r
439 /*-----------------------------------------------------------*/
\r
441 /*-----------------------------------------------------------------------
\r
442 * LED support for main_blinky()
\r
443 *------------------------------------------------------------------------
\r
445 uint32_t ulBlinkLED(void)
\r
447 if( uiLEDBlinkState == LED_OFF )
\r
449 uiLEDBlinkState = LED_ON;
\r
453 uiLEDBlinkState = LED_OFF;
\r
456 vGalileoBlinkLEDUsingLegacyGPIO(uiLEDBlinkState);
\r
458 return uiLEDBlinkState;
\r
460 /*-----------------------------------------------------------*/
\r
462 /*-----------------------------------------------------------------------
\r
463 * Serial port initialization code
\r
464 *------------------------------------------------------------------------
\r
466 static void vInitializeGalileoUART(uint32_t portnumber)
\r
468 volatile uint8_t divisor = 24;
\r
469 volatile uint8_t output_data = 0x3 & 0xFB & 0xF7;
\r
470 volatile uint8_t input_data = 0;
\r
471 volatile uint8_t lcr = 0;
\r
473 if (portnumber == DEBUG_SERIAL_PORT)
\r
474 UART_PCI_Base = MMIO_PCI_ADDRESS(0, 20, 5, 0);
\r
476 UART_PCI_Base = MMIO_PCI_ADDRESS(0, 20, 1, 0);
\r
478 uint32_t base = mem_read(UART_PCI_Base, 0x10, 4);
\r
479 UART_MMIO_Base = base;
\r
481 mem_write(base, R_UART_SCR, 1, 0xAB);
\r
483 mem_write(base, R_UART_LCR, 1, output_data | B_UARY_LCR_DLAB);
\r
485 mem_write(base, R_UART_BAUD_HIGH, 1, (uint8_t)(divisor >> 8));
\r
486 mem_write(base, R_UART_BAUD_LOW, 1, (uint8_t)(divisor & 0xff));
\r
488 mem_write(base, R_UART_LCR, 1, output_data);
\r
490 mem_write(base, R_UART_FCR, 1, (uint8_t)(B_UARY_FCR_TRFIFIE |
\r
491 B_UARY_FCR_RESETRF | B_UARY_FCR_RESETTF | 0x30));
\r
493 input_data = mem_read(base, R_UART_MCR, 1);
\r
494 input_data |= BIT1;
\r
495 input_data &= ~BIT5;
\r
496 mem_write(base, R_UART_MCR, 1, input_data);
\r
498 lcr = mem_read(base, R_UART_LCR, 1);
\r
499 mem_write(base, R_UART_LCR, 1, (uint8_t) (lcr & ~B_UARY_LCR_DLAB));
\r
501 mem_write(base, R_UART_IER, 1, 0);
\r
503 /*-----------------------------------------------------------*/
\r
505 void vInitializeGalileoSerialPort(uint32_t portnumber)
\r
507 if( bGalileoSerialPortInitialized == FALSE )
\r
509 /* Initialise for 115200, 8, 1, none and no handshaking */
\r
510 vInitializeGalileoUART(portnumber);
\r
511 bGalileoSerialPortInitialized = TRUE;
\r
514 /*-----------------------------------------------------------*/
\r
516 /*-----------------------------------------------------------------------
\r
517 * Serial port support functions
\r
518 *------------------------------------------------------------------------
\r
520 void vGalileoPrintc(char c)
\r
522 if (bGalileoSerialPortInitialized)
\r
524 while((mem_read(UART_MMIO_Base, R_UART_LSR, 1) & B_UART_LSR_TXRDY) == 0);
\r
525 mem_write(UART_MMIO_Base, R_UART_BAUD_THR, 1, c);
\r
528 /*-----------------------------------------------------------*/
\r
530 uint8_t ucGalileoGetchar()
\r
533 if (bGalileoSerialPortInitialized)
\r
535 if((mem_read(UART_MMIO_Base, R_UART_LSR, 1) & B_UART_LSR_RXRDY) != 0)
\r
536 c = mem_read(UART_MMIO_Base, R_UART_BAUD_THR, 1);
\r
540 /*-----------------------------------------------------------*/
\r
542 void vGalileoPuts(const char *string)
\r
544 if (bGalileoSerialPortInitialized)
\r
547 vGalileoPrintc(*string++);
\r
550 /*-----------------------------------------------------------*/
\r