// BIOS의 영역에서 MP Floating Header를 찾아서 그 주소를 반환 BOOL kFindMPFloatingPointerAddress(QWORD* pstAddress) { char* pcMPFloatingPointer; QWORD qwEBDAddress; QWORD qwSystemBaseMemory; // 확장 BIOS 데이터 영역과 시스템 기본 메모리를 출력 kPrintf("Extended BIOS Data Area = [0x%x]\n",(DWORD)(*(WORD*)0x040E)*16); kPrintf("System Base Address = [0x%x]\n",(DWORD)(*(WORD*)0x0413)*1024); // 확장 BIOS 데이터 영역은 검색하여 MP 플로팅 포인터를 찾음 // 확장 BIOS 데이터 영역은 0x040E에서 세그먼트으 시지가 어드레스를 찾을 수 있음 qwEBDAddress = *(WORD*)(0x040E); // 세그먼트의 시작 어드레스이므로 16을 곱하여 실제 물리 어드레스로 변환 qwEBDAddress *= 16; for(pcMPFloatingPointer = (char*)qwEBDAddress;(QWORD)pcMPFloatingPointer<=(qwEBDAddress+1024);pcMPFloatingPointer++) { if(kMemCmp(pcMPFloatingPointer,"_MP_",4)==0) { kPrintf("MP Floating Pointer Is In EBDA, [0x%x] Address\n",(DWORD)pcMPFloatingPointer); *pstAddress = (QWORD) pcMPFloatingPointer; return TRUE; } } // 시스템 기본 메모리의 끝부분에서 1KB 미만인 영역을 검색하여 MP 플로팅 포인터를 찾음 // 시스템 기본 메모리는 0x0413에서 KB 단위로 정렬된 값을 찾을 수 있음 // KB 단위로 저장된 값이므로 1024를 곱해 실제 물리 어드레스로 변환 qwSystemBaseMemory = *(WORD*)0x0413; qwSystemBaseMemory *= 1024; for(pcMPFloatingPointer = (char*) (qwSystemBaseMemory - 1024);(QWORD)pcMPFloatingPointer <= qwSystemBaseMemory ; pcMPFloatingPointer++) { if(kMemCmp(pcMPFloatingPointer,"_MP_",4)==0) { kPrintf("MP Floating Pointer Is In System Base Memory, [0x%x] Address\n",(DWORD)pcMPFloatingPointer); *pstAddress = (QWORD)pcMPFloatingPointer; return TRUE; } } // BIOS의 ROM 영역을 검색하여 MP 플로팅 포인터를 찾음 for(pcMPFloatingPointer = (char*)0x0F0000;(QWORD)pcMPFloatingPointer<0x0FFFFF;pcMPFloatingPointer++) { if(kMemCmp(pcMPFloatingPointer,"_MP_",4)==0) { kPrintf("MP Floating Pointer Is In ROM, [0x%x] Address\n",pcMPFloatingPointer); *pstAddress = (QWORD)pcMPFloatingPointer; return TRUE; } } return FALSE; }
/** * 태스크의 우선 순위를 변경 */ static void kChangeTaskPriority( const char* pcParameterBuffer ) { PARAMETERLIST stList; char vcID[ 30 ]; char vcPriority[ 30 ]; QWORD qwID; BYTE bPriority; // 파라미터를 추출 kInitializeParameter( &stList, pcParameterBuffer ); kGetNextParameter( &stList, vcID ); kGetNextParameter( &stList, vcPriority ); // 태스크의 우선 순위를 변경 if( kMemCmp( vcID, "0x", 2 ) == 0 ) { qwID = kAToI( vcID + 2, 16 ); } else { qwID = kAToI( vcID, 10 ); } bPriority = kAToI( vcPriority, 10 ); kPrintf( "Change Task Priority ID [0x%q] Priority[%d] ", qwID, bPriority ); if( kChangePriority( qwID, bPriority ) == TRUE ) { kPrintf( "Success\n" ); } else { kPrintf( "Fail\n" ); } }
// 루트 디렉터리에서 파일 이름이 일치하는 엔트리를 찾아서 인덱스를 반환 static int kFindDirectoryEntry(const char* pcFileName,DIRECTORYENTRY* pstEntry) { DIRECTORYENTRY* pstRootEntry; int i; int iLength; // 파일 시스템을 인식하지 못했으면 실패 if(gs_stFileSystemManager.bMounted==FALSE) { return -1; } // 루트 디렉터리를 읽음 if(kReadCluster(0,gs_vbTempBuffer)==FALSE) { return -1; } iLength = kStrLen(pcFileName); // 루트 디렉터리 안에서 루프를 돌면서 파일 이름이 일치하는 엔트리를 반환 pstRootEntry = (DIRECTORYENTRY*)gs_vbTempBuffer; for(i=0;i<FILESYSTEM_MAXDIRECTORYENTRYCOUNT;i++) { if(kMemCmp(pstRootEntry[i].vcFileName,pcFileName,iLength)==0) { kMemCpy(pstEntry,pstRootEntry+i,sizeof(DIRECTORYENTRY)); return i; } } return -1; }
/** * 태스크를 종료 */ static void kKillTask( const char* pcParameterBuffer ) { PARAMETERLIST stList; char vcID[ 30 ]; QWORD qwID; TCB* pstTCB; int i; // 파라미터를 추출 kInitializeParameter( &stList, pcParameterBuffer ); kGetNextParameter( &stList, vcID ); // 태스크를 종료 if( kMemCmp( vcID, "0x", 2 ) == 0 ) { qwID = kAToI( vcID + 2, 16 ); } else { qwID = kAToI( vcID, 10 ); } // 특정 ID만 종료하는 경우 if( qwID != 0xFFFFFFFF ) { pstTCB = kGetTCBInTCBPool( GETTCBOFFSET( qwID ) ); qwID = pstTCB->stLink.qwID; // 시스템 테스트는 제외 if( ( ( qwID >> 32 ) != 0 ) && ( ( pstTCB->qwFlags & TASK_FLAGS_SYSTEM ) == 0x00 ) ) { kPrintf( "Kill Task ID [0x%q] ", qwID ); if( kEndTask( qwID ) == TRUE ) { kPrintf( "Success\n" ); } else { kPrintf( "Fail\n" ); } } else {
/** * 문자열로 된 숫자를 숫자로 변환하여 화면에 출력 */ void kStringToDecimalHexTest( const char* pcParameterBuffer ) { char vcParameter[ 100 ]; int iLength; PARAMETERLIST stList; int iCount = 0; long lValue; // 파라미터 초기화 kInitializeParameter( &stList, pcParameterBuffer ); while( 1 ) { // 다음 파라미터를 구함, 파라미터의 길이가 0이면 파라미터가 없는 것이므로 // 종료 iLength = kGetNextParameter( &stList, vcParameter ); if( iLength == 0 ) { break; } // 파라미터에 대한 정보를 출력하고 16진수인지 10진수인지 판단하여 변환한 후 // 결과를 printf로 출력 kPrintf( "Param %d = '%s', Length = %d, ", iCount + 1, vcParameter, iLength ); // 0x로 시작하면 16진수, 그외는 10진수로 판단 if( kMemCmp( vcParameter, "0x", 2 ) == 0 ) { lValue = kAToI( vcParameter + 2, 16 ); kPrintf( "HEX Value = %q\n", lValue ); } else { lValue = kAToI( vcParameter, 10 ); kPrintf( "Decimal Value = %d\n", lValue ); } iCount++; } }
// Translate number string to number void kStringToDecimalHexTest( const char * pcParameterBuffer ) { char vcParameter[100]; int iLength; PARAMETERLIST stList; int iCount = 0; long lValue; // Initialize parameter kInitializeParameter( &stList, pcParameterBuffer ); while( 1 ) { // Get next parameter iLength = kGetNextParameter( &stList, vcParameter ); if( iLength == 0 ) { break; } // Print information of parameter // Detect 16 or 10 digit kPrintf( "Param %d = '%s', Length = %d, ", iCount + 1, vcParameter, iLength ); // If first is 0x, 16 digit // Other 10 digit if ( kMemCmp( vcParameter, "0x", 2 ) == 0 ) { lValue = kAToI( vcParameter + 2, 16 ); kPrintf( "HEX Value = %q\n", lValue ); } else { lValue = kAToI( vcParameter, 10 ); kPrintf( "Decimal Value = %d\n", lValue ); } iCount++; } }
/* * 커맨드 버퍼에 있는 커맨드를 비교하여 해당 커맨드를 처리하는 함수를 수행 */ void kExecuteCommand( const char* pcCommandBuffer ) { int i, iSpaceIndex; int iCommandBufferLength, iCommandLength; int iCount; // 공백으로 구분된 커맨드를 추출 iCommandBufferLength = kStrLen( pcCommandBuffer ); for( iSpaceIndex = 0 ; iSpaceIndex < iCommandBufferLength ; iSpaceIndex++ ) { if( pcCommandBuffer[ iSpaceIndex ] == ' ' ) { break; } } // 커맨드 테이블을 검사해서 동일한 이름의 커맨드가 있는지 확인 iCount = sizeof( gs_vstCommandTable ) / sizeof( SHELLCOMMANDENTRY ); for( i = 0 ; i < iCount ; i++ ) { iCommandLength = kStrLen( gs_vstCommandTable[ i ].pcCommand ); // 커맨드의 길이와 내용이 완전히 일치하는지 검사 if( ( iCommandLength == iSpaceIndex ) && ( kMemCmp( gs_vstCommandTable[ i ].pcCommand, pcCommandBuffer, iSpaceIndex ) == 0 ) ) { gs_vstCommandTable[ i ].pfFunction( pcCommandBuffer + iSpaceIndex + 1 ); break; } } // 리스트에서 찾을 수 없다면 에러 출력 if( i >= iCount ) { kPrintf( "'%s' is not found.\n", pcCommandBuffer ); } }
// Execute command if the command is one of the predefined void kExecuteCommand( const char * pcCommandBuffer ) { int i, iSpaceIndex; int iCommandBufferLength, iCommandLength; int iCount; // Extract command iCommandBufferLength = kStrLen( pcCommandBuffer ); for ( iSpaceIndex = 0 ; iSpaceIndex < iCommandBufferLength ; iSpaceIndex++ ) { if( pcCommandBuffer[iSpaceIndex] == ' ' ) { break; } } // Search the command in table iCount = sizeof( gs_vstCommandTable ) / sizeof( SHELLCOMMANDENTRY ); for ( i = 0 ; i < iCount ; i++ ) { iCommandLength = kStrLen( gs_vstCommandTable[i].pcCommand ); // Compare length and command if ( ( iCommandLength == iSpaceIndex ) && ( kMemCmp( gs_vstCommandTable[i].pcCommand, pcCommandBuffer, iSpaceIndex ) == 0 ) ) { gs_vstCommandTable[i].pfFunction( pcCommandBuffer + iSpaceIndex + 1 ); break; } } // If there is not same command if ( i >= iCount ) { kPrintf( "'%s' is not found.\n", pcCommandBuffer ); } }
/** * 이벤트 큐에 수신된 이벤트 처리 */ BOOL kProcessEventQueueData( void ) { EVENT vstEvent[ WINDOWMANAGER_DATAACCUMULATECOUNT ]; int iEventCount; WINDOWEVENT* pstWindowEvent; WINDOWEVENT* pstNextWindowEvent; QWORD qwWindowID; RECT stArea; RECT stOverlappedArea; int i; int j; //-------------------------------------------------------------------------- // 윈도우 매니저 태스크의 이벤트 큐에 수신된 이벤트를 통합하는 부분 //-------------------------------------------------------------------------- for( i = 0 ; i < WINDOWMANAGER_DATAACCUMULATECOUNT ; i++ ) { // 이벤트가 수신되기를 기다림 if( kReceiveEventFromWindowManagerQueue( &( vstEvent[ i ] ) ) == FALSE ) { // 처음부터 이벤트가 수신되지 않았으면 종료 if( i == 0 ) { return FALSE; } else { break; } } pstWindowEvent = &( vstEvent[ i ].stWindowEvent ); // 윈도우 ID로 업데이트하는 이벤트가 수신되면 윈도우 영역을 이벤트 데이터에 삽입 if( vstEvent[ i ].qwType == EVENT_WINDOWMANAGER_UPDATESCREENBYID ) { // 윈도우의 크기를 이벤트 자료구조에 삽입 if( kGetWindowArea( pstWindowEvent->qwWindowID, &stArea ) == FALSE ) { kSetRectangleData( 0, 0, 0, 0, &( pstWindowEvent->stArea ) ); } else { kSetRectangleData( 0, 0, kGetRectangleWidth( &stArea ) - 1, kGetRectangleHeight( &stArea ) - 1, &( pstWindowEvent->stArea ) ); } } } // 저장된 이벤트를 검사하면서 합칠 수 있는 이벤트는 하나로 만듦 iEventCount = i; for( j = 0 ; j < iEventCount ; j++ ) { // 수신된 이벤트 중에 이벤트 중에서 이번에 처리할 것과 같은 윈도우에서 // 발생하는 윈도우 이벤트를 검색 pstWindowEvent = &( vstEvent[ j ].stWindowEvent ); if( ( vstEvent[ j ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYID ) && ( vstEvent[ j ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYWINDOWAREA ) && ( vstEvent[ j ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYSCREENAREA ) ) { continue; } // 수신한 이벤트의 끝까지 루프를 수행하면서 수신된 이벤트를 검사 for( i = j + 1 ; i < iEventCount ; i++ ) { pstNextWindowEvent = &( vstEvent[ i ].stWindowEvent ); // 화면 업데이트가 아니거나 윈도우 ID가 일치하지 않으면 제외 if( ( ( vstEvent[ i ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYID ) && ( vstEvent[ i ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYWINDOWAREA ) && ( vstEvent[ i ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYSCREENAREA ) ) || ( pstWindowEvent->qwWindowID != pstNextWindowEvent->qwWindowID ) ) { continue; } // 겹치는 영역을 계산하여 겹치지 않으면 제외 if( kGetOverlappedRectangle( &( pstWindowEvent->stArea ), &( pstNextWindowEvent->stArea ), &stOverlappedArea ) == FALSE ) { continue; } // 두 영역이 일치하거나 어느 한쪽이 포함되면 이벤트를 통합 if( kMemCmp( &( pstWindowEvent->stArea ), &stOverlappedArea, sizeof( RECT ) ) == 0 ) { // 현재 이벤트의 윈도우의 영역이 겹치는 영역과 일치한다면 // 다음 이벤트의 윈도우 영역이 현재 윈도우 영역과 같거나 포함함 // 따라서 현재 이벤트에 다음 이벤트의 윈도우 영역을 복사하고 // 다음 이벤트는 삭제 kMemCpy( &( pstWindowEvent->stArea ), &( pstNextWindowEvent->stArea ), sizeof( RECT ) ); vstEvent[ i ].qwType = EVENT_UNKNOWN; } else if( kMemCmp( &( pstNextWindowEvent->stArea ), &stOverlappedArea, sizeof( RECT ) ) == 0 ) { // 다음 이벤트의 윈도우의 영역이 겹치는 영역과 일치한다면 // 현재 이벤트의 윈도우 영역이 다음 윈도우 영역과 같거나 포함함 // 따라서 윈도우 영역을 복사하지 않고 다음 이벤트를 삭제 vstEvent[ i ].qwType = EVENT_UNKNOWN; } } } // 통합된 이벤트를 모두 처리 for( i = 0 ; i < iEventCount ; i++ ) { pstWindowEvent = &( vstEvent[ i ].stWindowEvent ); // 타입 별로 처리 switch( vstEvent[ i ].qwType ) { // 현재 윈도우가 있는 영역을 화면에 업데이트 case EVENT_WINDOWMANAGER_UPDATESCREENBYID: // 윈도우의 내부 영역을 화면에 업데이트 case EVENT_WINDOWMANAGER_UPDATESCREENBYWINDOWAREA: // 윈도우를 기준으로 한 좌표를 화면 좌표로 변환하여 업데이트 처리 if( kConvertRectClientToScreen( pstWindowEvent->qwWindowID, &( pstWindowEvent->stArea ), &stArea ) == TRUE ) { // 윈도우 영역은 위에서 했으므로 그대로 화면 업데이트 함수를 호출 kRedrawWindowByArea( &stArea, pstWindowEvent->qwWindowID ); } break; // 화면 좌표로 전달된 영역을 화면에 업데이트 case EVENT_WINDOWMANAGER_UPDATESCREENBYSCREENAREA: kRedrawWindowByArea( &( pstWindowEvent->stArea ), WINDOW_INVALIDID ); break; default: break; } } return TRUE; }
/** * MP 설정 테이블을 분석해서 필요한 정보를 저장하는 함수 */ BOOL kAnalysisMPConfigurationTable( void ) { QWORD qwMPFloatingPointerAddress; MPFLOATINGPOINTER* pstMPFloatingPointer; MPCONFIGURATIONTABLEHEADER* pstMPConfigurationHeader; BYTE bEntryType; WORD i; QWORD qwEntryAddress; PROCESSORENTRY* pstProcessorEntry; BUSENTRY* pstBusEntry; // 자료구조 초기화 kMemSet( &gs_stMPConfigurationManager, 0, sizeof( MPCONFIGRUATIONMANAGER ) ); gs_stMPConfigurationManager.bISABusID = 0xFF; // MP 플로팅 포인터의 어드레스를 구함 if( kFindMPFloatingPointerAddress( &qwMPFloatingPointerAddress ) == FALSE ) { return FALSE; } // MP 플로팅 테이블 설정 pstMPFloatingPointer = ( MPFLOATINGPOINTER* ) qwMPFloatingPointerAddress; gs_stMPConfigurationManager.pstMPFloatingPointer = pstMPFloatingPointer; pstMPConfigurationHeader = ( MPCONFIGURATIONTABLEHEADER* ) ( ( QWORD ) pstMPFloatingPointer->dwMPConfigurationTableAddress & 0xFFFFFFFF ); // PIC 모드 지원 여부 저장 if( pstMPFloatingPointer->vbMPFeatureByte[ 1 ] & MP_FLOATINGPOINTER_FEATUREBYTE2_PICMODE ) { gs_stMPConfigurationManager.bUsePICMode = TRUE; } // MP 설정 테이블 헤더와 기본 MP 설정 테이블 엔트리의 시작 어드레스 설정 gs_stMPConfigurationManager.pstMPConfigurationTableHeader = pstMPConfigurationHeader; gs_stMPConfigurationManager.qwBaseEntryStartAddress = pstMPFloatingPointer->dwMPConfigurationTableAddress + sizeof( MPCONFIGURATIONTABLEHEADER ); // 모든 엔트리를 돌면서 프로세서의 코어 수를 계산하고 ISA 버스를 검색하여 ID를 저장 qwEntryAddress = gs_stMPConfigurationManager.qwBaseEntryStartAddress; for( i = 0 ; i < pstMPConfigurationHeader->wEntryCount ; i++ ) { bEntryType = *( BYTE* ) qwEntryAddress; switch( bEntryType ) { // 프로세서 엔트리이면 프로세서의 수를 하나 증가시킴 case MP_ENTRYTYPE_PROCESSOR: pstProcessorEntry = ( PROCESSORENTRY* ) qwEntryAddress; if( pstProcessorEntry->bCPUFlags & MP_PROCESSOR_CPUFLAGS_ENABLE ) { gs_stMPConfigurationManager.iProcessorCount++; } qwEntryAddress += sizeof( PROCESSORENTRY ); break; // 버스 엔트리이면 ISA 버스인지 확인하여 저장 case MP_ENTRYTYPE_BUS: pstBusEntry = ( BUSENTRY* ) qwEntryAddress; if( kMemCmp( pstBusEntry->vcBusTypeString, MP_BUS_TYPESTRING_ISA, kStrLen( MP_BUS_TYPESTRING_ISA ) ) == 0 ) { gs_stMPConfigurationManager.bISABusID = pstBusEntry->bBusID; } qwEntryAddress += sizeof( BUSENTRY ); break; // 기타 엔트리는 무시하고 이동 case MP_ENTRYTYPE_IOAPIC: case MP_ENTRYTYPE_IOINTERRUPTASSIGNMENT: case MP_ENTRYTYPE_LOCALINTERRUPTASSIGNMENT: default: qwEntryAddress += 8; break; } } return TRUE; }