/** * 태스크를 생성해서 멀티 태스킹 수행 */ void kCreateTestTask( const char* pcParameterBuffer ) { PARAMETERLIST stList; char vcType[ 30 ]; char vcCount[ 30 ]; int i; // 파라미터를 추출 kInitializeParameter( &stList, pcParameterBuffer ); kGetNextParameter( &stList, vcType ); kGetNextParameter( &stList, vcCount ); switch( kAToI( vcType, 10 ) ) { // 타입 1 태스크 생성 case 1: for( i = 0 ; i < kAToI( vcCount, 10 ) ; i++ ) { if( kCreateTask( 0, ( QWORD ) kTestTask1 ) == NULL ) { break; } } kPrintf( "Task1 %d Created\n", i ); break; // 타입 2 태스크 생성 case 2: default: for( i = 0 ; i < kAToI( vcCount, 10 ) ; i++ ) { if( kCreateTask( 0, ( QWORD ) kTestTask2 ) == NULL ) { break; } } kPrintf( "Task2 %d Created\n", i ); break; } }
void Main( void ) { int iCursorX, iCursorY; kPrintString( 45, 10,"Pass" ); kInitializeConsole( 0, 11); kPrintf("Success to enter 64-bit C Kernel\n"); kPrintf("Console Initialization......................[Pass]\n"); // 부팅상황 kGetCursor( &iCursorX, &iCursorY ); kPrintf("GDT Initialize And Switch For 64bit Mode....[ ]"); kInitializeGDTTableAndTSS(); kLoadGDTR( GDTR_STARTADDRESS ); kSetCursor( 45, iCursorY++); kPrintf("Pass\n"); kPrintf("TSS Segment Load............................[ ]" ); kLoadTR( GDT_TSSSEGMENT ); kSetCursor( 45, iCursorY++); kPrintf("Pass\n"); kPrintf("IDT Initialize..............................[ ]" ); kInitializeIDTTables(); kLoadIDTR( IDTR_STARTADDRESS ); kSetCursor( 45, iCursorY++); kPrintf("Pass\n"); kPrintf("Total RAM Size Check........................[ ]" ); kCheckTotalRAMSize(); kSetCursor( 45, iCursorY++); kPrintf("Pass], Size = %d MB\n", kGetTotalRAMSize()); kPrintf("TCB Pool And Scheduler Initialize...........[Pass]\n" ); iCursorY++; kInitializeScheduler(); kPrintf("Dynamic Memory Initialize...................[Pass]\n"); iCursorY++; kInitializeDynamicMemory(); // 1ms 당 인터럽트 발생 kInitializePIT( MSTOCOUNT(1), 1 ); kPrintf("Keyboard Activation.........................[ ]" ); if( kInitializeKeyboard() == TRUE ) { kSetCursor( 45, iCursorY++); kPrintf("Pass\n"); kChangeKeyboardLED(FALSE, FALSE, FALSE); } else { kSetCursor( 45, iCursorY++); kPrintf("Fail\n"); while(1) { ; } } kPrintf("PIC Controller And Interrupt Initialize.....[ ]" ); kInitializePIC(); kMaskPICInterrupt( 0 ); kEnableInterrupt(); kSetCursor( 45, iCursorY++); kPrintf("Pass\n"); kPrintf("HDD Initialize..............................[ ]" ); if(kInitializeHDD() == TRUE) { kSetCursor( 45, iCursorY++); kPrintf("Pass\n"); } else { kSetCursor( 45, iCursorY++); kPrintf("Fail\n"); } kPrintf("File System Initialize......................[ ]" ); if(kInitializeFileSystem() == TRUE) { kSetCursor( 45, iCursorY++); kPrintf("Pass\n"); } else { kSetCursor( 45, iCursorY++); kPrintf("Fail\n"); } kCreateTask( TASK_FLAGS_LOWEST | TASK_FLAGS_IDLE | TASK_FLAGS_SYSTEM | TASK_FLAGS_THREAD , 0, 0, (QWORD) kIdleTask ); kStartConsoleShell(); }
/** * 수신된 마우스 데이터를 처리 */ BOOL kProcessMouseData( void ) { QWORD qwWindowIDUnderMouse; BYTE bButtonStatus; int iRelativeX, iRelativeY; int iMouseX, iMouseY; int iPreviousMouseX, iPreviousMouseY; BYTE bChangedButton; RECT stWindowArea; EVENT stEvent; WINDOWMANAGER* pstWindowManager; char vcTempTitle[ WINDOW_TITLEMAXLENGTH ]; int i; // 윈도우 매니저를 반환 pstWindowManager = kGetWindowManager(); //-------------------------------------------------------------------------- // 마우스 이벤트를 통합하는 부분 //-------------------------------------------------------------------------- for( i = 0 ; i < WINDOWMANAGER_DATAACCUMULATECOUNT ; i++ ) { // 마우스 데이터가 수신되기를 기다림 if( kGetMouseDataFromMouseQueue( &bButtonStatus, &iRelativeX, &iRelativeY ) == FALSE ) { // 처음으로 확인했는데 데이터가 없다면 종료 if( i == 0 ) { return FALSE; } // 처음이 아닌 경우는 이전 루프에서 마우스 이벤트를 수신했으므로 // 통합한 이벤트를 처리 else { break; } } // 현재 마우스 커서 위치를 반환 kGetCursorPosition( &iMouseX, &iMouseY ); // 처음 마우스 이벤트가 수신된 것이면 현재 좌표를 이전 마우스의 위치로 저장해둠 if( i == 0 ) { // 움직이기 이전의 좌표를 저장 iPreviousMouseX = iMouseX; iPreviousMouseY = iMouseY; } // 마우스가 움직인 거리를 이전 커서 위치에 더해서 현재 좌표를 계산 iMouseX += iRelativeX; iMouseY += iRelativeY; // 새로운 위치로 마우스 커서를 이동하고 다시 현재 커서의 위치를 반환 // 마우스 커서가 화면을 벗어나지 않도록 처리된 커서 좌표를 사용하여 화면을 벗어난 // 커서로 인해 발생하는 문제를 방지 kMoveCursor( iMouseX, iMouseY ); kGetCursorPosition( &iMouseX, &iMouseY ); // 버튼 상태는 이전 버튼 상태와 현재 버튼 상태를 XOR하여 1로 설정됐는지를 확인 bChangedButton = pstWindowManager->bPreviousButtonStatus ^ bButtonStatus; // 마우스가 움직였으나 버튼의 변화가 있다면 바로 이벤트 처리 if( bChangedButton != 0 ) { break; } } //-------------------------------------------------------------------------- // 마우스 이벤트를 처리하는 부분 //-------------------------------------------------------------------------- // 현재 마우스 커서 아래에 있는 윈도우를 검색 qwWindowIDUnderMouse = kFindWindowByPoint( iMouseX, iMouseY ); //-------------------------------------------------------------------------- // 버튼 상태가 변했는지 확인하고 버튼 상태에 따라 마우스 메시지와 윈도우 메시지를 // 전송 //-------------------------------------------------------------------------- // 마우스 왼쪽 버튼에 변화가 생긴 경우 처리 if( bChangedButton & MOUSE_LBUTTONDOWN ) { // 왼쪽 버튼이 눌린 경우 처리 if( bButtonStatus & MOUSE_LBUTTONDOWN ) { // 마우스로 윈도우를 선택한 것이므로, 마우스 아래에 있는 윈도우가 // 배경 윈도우가 아닌 경우 최상위로 올려줌 if( qwWindowIDUnderMouse != pstWindowManager->qwBackgoundWindowID ) { // 선택된 윈도우를 최상위로 만듦 // 윈도우를 최상위로 만들면서 동시에 윈도우 선택과 선택 해제 이벤트도 // 같이 전송 kMoveWindowToTop( qwWindowIDUnderMouse ); } //------------------------------------------------------------------ // 왼쪽 버튼이 눌린 위치가 제목 표시줄의 위치이면 윈도우 이동인지 또는 // 닫기 버튼 위치에서 눌렸는지 확인하여 처리 //------------------------------------------------------------------ if( kIsInTitleBar( qwWindowIDUnderMouse, iMouseX, iMouseY ) == TRUE ) { // 닫기 버튼에서 눌러졌으면 윈도우에 닫기 전송 if( kIsInCloseButton( qwWindowIDUnderMouse, iMouseX, iMouseY ) == TRUE ) { // 윈도우 닫기 이벤트를 전송 kSetWindowEvent( qwWindowIDUnderMouse, EVENT_WINDOW_CLOSE, &stEvent ); kSendEventToWindow( qwWindowIDUnderMouse, &stEvent ); } // 닫기 버튼이 아니면 윈도우 이동 모드로 변경 else { // 윈도우 이동 모드 설정 pstWindowManager->bWindowMoveMode = TRUE; // 현재 윈도우를 이동하는 윈도우로 설정 pstWindowManager->qwMovingWindowID = qwWindowIDUnderMouse; } } // 윈도우 내부에서 눌린 것이면 왼쪽 버튼이 눌러졌음을 전송 else { // 왼쪽 버튼 눌림 이벤트를 전송 kSetMouseEvent( qwWindowIDUnderMouse, EVENT_MOUSE_LBUTTONDOWN, iMouseX, iMouseY, bButtonStatus, &stEvent ); kSendEventToWindow( qwWindowIDUnderMouse, &stEvent ); } } // 왼쪽 버튼이 떨어진 경우 처리 else { // 윈도우가 이동 중이었으면 모드만 해제 if( pstWindowManager->bWindowMoveMode == TRUE ) { // 이동 중이라는 플래그를 해제 pstWindowManager->bWindowMoveMode = FALSE; pstWindowManager->qwMovingWindowID = WINDOW_INVALIDID; } // 윈도우가 이동 중이 아니었으면 윈도우로 왼쪽 버튼 떨어짐 이벤트를 전송 else { // 왼쪽 버튼 떨어짐 이벤트를 전송 kSetMouseEvent( qwWindowIDUnderMouse, EVENT_MOUSE_LBUTTONUP, iMouseX, iMouseY, bButtonStatus, &stEvent ); kSendEventToWindow( qwWindowIDUnderMouse, &stEvent ); } } } // 마우스 오른쪽 버튼에 변화가 생긴 경우 처리 else if( bChangedButton & MOUSE_RBUTTONDOWN ) { // 오른쪽 버튼이 눌린 경우 처리 if( bButtonStatus & MOUSE_RBUTTONDOWN ) { // 오른쪽 버튼 눌림 이벤트를 전송 kSetMouseEvent( qwWindowIDUnderMouse, EVENT_MOUSE_RBUTTONDOWN, iMouseX, iMouseY, bButtonStatus, &stEvent ); kSendEventToWindow( qwWindowIDUnderMouse, &stEvent ); //------------------------------------------------------------------ // 테스트를 위해 일시적으로 추가된 부분 //------------------------------------------------------------------ // 테스트를 위해 오른쪽 버튼이 눌리면 GUI 태스크를 생성 kCreateTask( TASK_FLAGS_LOW | TASK_FLAGS_THREAD, NULL, NULL, ( QWORD ) kHelloWorldGUITask, TASK_LOADBALANCINGID ); } else { // 오른쪽 버튼 떨어짐 이벤트를 전송 kSetMouseEvent( qwWindowIDUnderMouse, EVENT_MOUSE_RBUTTONUP, iMouseX, iMouseY, bButtonStatus, &stEvent ); kSendEventToWindow( qwWindowIDUnderMouse, &stEvent ); } } // 마우스 가운데 버튼에 변화가 생긴 경우 처리 else if( bChangedButton & MOUSE_MBUTTONDOWN ) { // 가운데 버튼이 눌린 경우 처리 if( bButtonStatus & MOUSE_MBUTTONDOWN ) { // 가운데 버튼 눌림 이벤트를 전송 kSetMouseEvent( qwWindowIDUnderMouse, EVENT_MOUSE_MBUTTONDOWN, iMouseX, iMouseY, bButtonStatus, &stEvent ); kSendEventToWindow( qwWindowIDUnderMouse, &stEvent ); } else { // 가운데 버튼 떨어짐 이벤트를 전송 kSetMouseEvent( qwWindowIDUnderMouse, EVENT_MOUSE_MBUTTONUP, iMouseX, iMouseY, bButtonStatus, &stEvent ); kSendEventToWindow( qwWindowIDUnderMouse, &stEvent ); } } // 마우스 버튼이 변경되지 않았으면 마우스 이동 처리만 수행 else { // 마우스 이동 이벤트를 전송 kSetMouseEvent( qwWindowIDUnderMouse, EVENT_MOUSE_MOVE, iMouseX, iMouseY, bButtonStatus, &stEvent ); kSendEventToWindow( qwWindowIDUnderMouse, &stEvent ); } // 윈도우가 이동 중이었으면 윈도우 이동 처리 if( pstWindowManager->bWindowMoveMode == TRUE ) { // 윈도우의 위치를 얻음 if( kGetWindowArea( pstWindowManager->qwMovingWindowID, &stWindowArea ) == TRUE ) { // 윈도우의 현재 위치를 얻어서 마우스가 이동한 만큼 옮겨줌 // 윈도우 이동 이벤트는 함수 내부에서 전달 kMoveWindow( pstWindowManager->qwMovingWindowID, stWindowArea.iX1 + iMouseX - iPreviousMouseX, stWindowArea.iY1 + iMouseY - iPreviousMouseY ); } // 윈도우의 위치를 얻을 수 없으면 윈도우가 존재하지 않는 것이므로 // 윈도우 이동 모드 해제 else { // 이동 중이라는 플래그를 해제 pstWindowManager->bWindowMoveMode = FALSE; pstWindowManager->qwMovingWindowID = WINDOW_INVALIDID; } } // 다음 처리에 사용하려고 현재 버튼 상태를 저장함 pstWindowManager->bPreviousButtonStatus = bButtonStatus; return TRUE; }
/** * GUI 버전의 콘솔 셸 태스크 */ void kGUIConsoleShellTask( void ) { static QWORD s_qwWindowID = WINDOW_INVALIDID; int iWindowWidth, iWindowHeight; EVENT stReceivedEvent; KEYEVENT* pstKeyEvent; RECT stScreenArea; KEYDATA stKeyData; TCB* pstConsoleShellTask; QWORD qwConsoleShellTaskID; //-------------------------------------------------------------------------- // 그래픽 모드 판단 //-------------------------------------------------------------------------- // MINT64 OS가 그래픽 모드로 시작했는지 확인 if( kIsGraphicMode() == FALSE ) { // MINT64 OS가 그래픽 모드로 시작하지 않았다면 실패 kPrintf( "This task can run only GUI mode~!!!\n" ); return ; } // GUI 콘솔 셸 윈도우가 존재하면 생성된 윈도우를 최상위로 만들고 태스크 종료 if( s_qwWindowID != WINDOW_INVALIDID ) { kMoveWindowToTop( s_qwWindowID ); return ; } //-------------------------------------------------------------------------- // 윈도우를 생성 //-------------------------------------------------------------------------- // 전체 화면 영역의 크기를 반환 kGetScreenArea( &stScreenArea ); // 윈도우의 크기 설정, 화면 버퍼에 들어가는 문자의 최대 너비와 높이를 고려해서 계산 iWindowWidth = CONSOLE_WIDTH * FONT_ENGLISHWIDTH + 4; iWindowHeight = CONSOLE_HEIGHT * FONT_ENGLISHHEIGHT + WINDOW_TITLEBAR_HEIGHT + 2; // 윈도우 생성 함수 호출, 화면 가운데에 생성 s_qwWindowID = kCreateWindow( ( stScreenArea.iX2 - iWindowWidth ) / 2, ( stScreenArea.iY2 - iWindowHeight ) / 2, iWindowWidth, iWindowHeight, WINDOW_FLAGS_DEFAULT, "Console Shell for GUI" ); // 윈도우를 생성하지 못했으면 실패 if( s_qwWindowID == WINDOW_INVALIDID ) { return ; } // 셸 커맨드를 처리하는 콘솔 셸 태스크를 생성 kSetConsoleShellExitFlag( FALSE ); pstConsoleShellTask = kCreateTask( TASK_FLAGS_LOW | TASK_FLAGS_THREAD, 0, 0, ( QWORD ) kStartConsoleShell, TASK_LOADBALANCINGID ); if( pstConsoleShellTask == NULL ) { // 콘솔 셸 태스크 생성에 실패하면 윈도우를 삭제하고 종료 kDeleteWindow( s_qwWindowID ); return ; } // 콘솔 셸 태스크의 ID를 저장 qwConsoleShellTaskID = pstConsoleShellTask->stLink.qwID; // 이전 화면 버퍼를 초기화 kMemSet( gs_vstPreviousScreenBuffer, 0xFF, sizeof( gs_vstPreviousScreenBuffer ) ); //-------------------------------------------------------------------------- // GUI 태스크의 이벤트 처리 루프 //-------------------------------------------------------------------------- while( 1 ) { // 화면 버퍼의 변경된 내용을 윈도우에 업데이트 kProcessConsoleBuffer( s_qwWindowID ); // 이벤트 큐에서 이벤트를 수신 if( kReceiveEventFromWindowQueue( s_qwWindowID, &stReceivedEvent ) == FALSE ) { kSleep( 0 ); continue; } // 수신된 이벤트를 타입에 따라 나누어 처리 switch( stReceivedEvent.qwType ) { // 키 이벤트 처리 case EVENT_KEY_DOWN: case EVENT_KEY_UP: // 여기에 키보드 이벤트 처리 코드 넣기 pstKeyEvent = &( stReceivedEvent.stKeyEvent ); stKeyData.bASCIICode = pstKeyEvent->bASCIICode; stKeyData.bFlags = pstKeyEvent->bFlags; stKeyData.bScanCode = pstKeyEvent->bScanCode; // 키를 그래픽 모드용 키 큐로 삽입하여 셸 태스크의 입력으로 전달 kPutKeyToGUIKeyQueue( &stKeyData ); break; // 윈도우 이벤트 처리 case EVENT_WINDOW_CLOSE: // 생성한 셸 태스크가 종료되도록 종료 플래그를 설정하고 종료될 때까지 대기 kSetConsoleShellExitFlag( TRUE ); while( kIsTaskExist( qwConsoleShellTaskID ) == TRUE ) { kSleep( 1 ); } // 윈도우를 삭제하고 윈도우 ID를 초기화 kDeleteWindow( s_qwWindowID ); s_qwWindowID = WINDOW_INVALIDID; return ; break; // 그 외 정보 default: // 여기에 알 수 없는 이벤트 처리 코드 넣기 break; } } }
// Bootstrap Processor용 C 언어 커널 엔트리 포인트 void main( void ) { int iCursorX, iCursorY; // 부트 로더에 있는 BSP 플래그를 읽어서 Application Processor이면 // 해당 코어용 초기화 함수로 이동 if(*((BYTE*)BOOTSTRAPPROCESSOR_FLAGADDESS)==0) { mainForApplicationProcessor(); } // Bootstrap Processor가 부팅을 완료했으므로, 0x7C09에 있는 Bootstrap Processor를 // 나타내는 플래그를 0으로 설정하여 Application Processor용으로 코드 실행 경로를 변경 *((BYTE*)BOOTSTRAPPROCESSOR_FLAGADDESS)=0; // 콘솔을 먼저 초기화한 후, 다음 작업을 수행 kInitializeConsole( 0, 10 ); kPrintf( "Switch To IA-32e Mode Success~!!\n" ); kPrintf( "IA-32e C Language Kernel Start..............[Pass]\n" ); kPrintf( "Initialize Console..........................[Pass]\n" ); // 부팅 상황을 화면에 출력 kGetCursor( &iCursorX, &iCursorY ); kPrintf( "GDT Initialize And Switch For IA-32e Mode...[ ]" ); kInitializeGDTTableAndTSS(); kLoadGDTR( GDTR_STARTADDRESS ); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); kPrintf( "TSS Segment Load............................[ ]" ); kLoadTR( GDT_TSSSEGMENT ); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); kPrintf( "IDT Initialize..............................[ ]" ); kInitializeIDTTables(); kLoadIDTR( IDTR_STARTADDRESS ); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); kPrintf( "Total RAM Size Check........................[ ]" ); kCheckTotalRAMSize(); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass], Size = %d MB\n", kGetTotalRAMSize() ); kPrintf("TCB Poll And Scheduler Initialize...........[Pass]\n"); iCursorY++; kInitializeScheduler(); // 동적 메모리 초기화 kPrintf("Dynamic Memory Initialize...................[Pass]\n"); iCursorY++; kInitializeDynamicMemory(); // 1ms당 한 번씩 인터럽트가 발생하도록 설정 kInitializePIT(MSTOCOUNT(1),1); kPrintf( "Keyboard Activate And Queue Initialize......[ ]" ); // 키보드를 활성화 if( kInitializeKeyboard() == TRUE ) { kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); kChangeKeyboardLED( FALSE, FALSE, FALSE ); } else { kSetCursor( 45, iCursorY++ ); kPrintf( "Fail\n" ); while( 1 ) ; } kPrintf( "PIC Controller And Interrupt Initialize.....[ ]" ); // PIC 컨트롤러 초기화 및 모든 인터럽트 활성화 kInitializePIC(); kMaskPICInterrupt( 0 ); kEnableInterrupt(); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); // 파일 시스템을 초기화 kPrintf("File System Initialize......................[ ]"); if(kInitializeFileSystem()==TRUE) { kSetCursor(45,iCursorY++); kPrintf("Pass\n"); } else { kSetCursor(45,iCursorY++); kPrintf("Fail\n"); } // 시리얼 포트 초기화 kPrintf("Serial Port Initialize......................[Pass]\n"); iCursorY++; kInitializeSerialPort(); // 유후 태스크를 시스템 스레드로 생성하고 셸을 시작 kCreateTask(TASK_FLAGS_LOWEST | TASK_FLAGS_THREAD | TASK_FLAGS_SYSTEM | TASK_FLAGS_IDLE,0,0,(QWORD)kIdleTask,kGetAPICID()); // 그래픽 모드가 아니면 콘솔 셸 실행 if(*(BYTE*)VBE_STARTGRAPHICMODEFLAGADDRESS==0) { kStartConsoleShell(); } // 그래픽 모드면 그래픽 모드 테스트 함수 실행 else { kStartGraphicModeTest(); } }
/** * 아래 함수는 C 언어 커널의 시작 부분임 */ void Main( void ) { int iCursorX, iCursorY; // 콘솔을 먼저 초기화한 후, 다음 작업을 수행 kInitializeConsole( 0, 10 ); kPrintf( "Switch To IA-32e Mode Success~!!\n" ); kPrintf( "IA-32e C Language Kernel Start..............[Pass]\n" ); kPrintf( "Initialize Console..........................[Pass]\n" ); // 부팅 상황을 화면에 출력 kGetCursor( &iCursorX, &iCursorY ); kPrintf( "GDT Initialize And Switch For IA-32e Mode...[ ]" ); kInitializeGDTTableAndTSS(); kLoadGDTR( GDTR_STARTADDRESS ); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); kPrintf( "TSS Segment Load............................[ ]" ); kLoadTR( GDT_TSSSEGMENT ); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); kPrintf( "IDT Initialize..............................[ ]" ); kInitializeIDTTables(); kLoadIDTR( IDTR_STARTADDRESS ); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); kPrintf( "Total RAM Size Check........................[ ]" ); kCheckTotalRAMSize(); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass], Size = %d MB\n", kGetTotalRAMSize() ); kPrintf( "TCB Pool And Scheduler Initialize...........[Pass]\n" ); iCursorY++; kInitializeScheduler(); // 1ms당 한번씩 인터럽트가 발생하도록 설정 kInitializePIT( MSTOCOUNT( 1 ), 1 ); kPrintf( "Keyboard Activate And Queue Initialize......[ ]" ); // 키보드를 활성화 if( kInitializeKeyboard() == TRUE ) { kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); kChangeKeyboardLED( FALSE, FALSE, FALSE ); } else { kSetCursor( 45, iCursorY++ ); kPrintf( "Fail\n" ); while( 1 ) ; } kPrintf( "PIC Controller And Interrupt Initialize.....[ ]" ); // PIC 컨트롤러 초기화 및 모든 인터럽트 활성화 kInitializePIC(); kMaskPICInterrupt( 0 ); kEnableInterrupt(); kSetCursor( 45, iCursorY++ ); kPrintf( "Pass\n" ); // 유휴 태스크를 생성하고 셸을 시작 kCreateTask( TASK_FLAGS_LOWEST | TASK_FLAGS_IDLE, ( QWORD ) kIdleTask ); kStartConsoleShell(); }