bloggerads

2017年1月13日 星期五

DOS : Increase Dosbox screen size in Windows

Step 1. Find dosbox-0.74.conf

Step 2. Modify the SDL part in the dosbox-0.74.conf


[SDL]

fullscreen=false 
fulldouble=false 
fullresolution=original 
windowresolution=1024x768 
output=ddraw 
autolock=true 
sensitivity=100 
waitonerror=true 
priority=higher,normal 
mapperfile=mapper.txt 
usescancodes=true 

ps. Some Dos application may consume lot of CPU usage. Fix it by Setting a fixed CPU cycles, for example, 16000.
[CPU]
cycles=auto 
cycles=16000

2016年12月2日 星期五

gcc : Built-in functions for atomic memory access

這一篇是研究Memory barrier的心得。研究的原因是因為在UEFI環境下使用multi-processor protocol 來驗證CPU design,過程用到了相關的gcc Atomic函式。Atomic 提供同步機制,使得在Multi-Processor/Multi-Thread的系統下操作同一塊memory, 各個Core的Cache都能確保和Memory同步。

這邊只是以軟體thread寫個應用程式作範例來解釋Memory barrier, 如果不使用Built-in functions for atomic memory access而將__sync_fetch_and_add(&count,1);改成count++, 則count結果會不正確。

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

static int count = 0;

void *MyTest(void *arg)
{
        for (int i=0; i<20000; ++i)         
            __sync_fetch_and_add(&count, 1);
        return NULL;
}

int main(int argc, const char *argv[])
{
        pthread_t Thread_Id[10];
        int i;

        for (i=0;i<10;++i)
                pthread_create(&Thread_Id[i], NULL, MyTest, NULL);
       
                // Wait until all threads have finished.
        for (i=0;i<10;++i)
                pthread_join(Thread_Id[i], NULL);
       
        printf("%d\n",count);
        return 0;
}


另外,__sync_synchronize (): This built-in function issues a full memory barrier.呼叫這個函式讓每個Core上的cache和memory同步。

<note> UEFI kernel提供EFI_MP_SERVICES_PROTOCOL,透過這個protocol,可以指定呼叫某個/或多個CORE (AP)分別執行特定的function,達到Multi-processing的效果。

-------------------------------------------------------------------------------------------------------------------------
Ps. windows下測試,需要自行加入pthread這個library
如果你用Dev-C++ 5.11, Project->Parameters->Add library or object 加入
"../../Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libpthread.a"



順便解釋一下我認知的procces/thread:

process: 在系統中被註冊要執行的程式,其擁有CPU的使用權和獨立的位址空間。
thread: 系統處理工作的基本單位,一個CPU核心在同一時間只能提供一個thread來執行process
Multi-Thread: 將多個thread同時assign給一個process
Multi-Process: 每個process都分到thread來處理

2016年12月1日 星期四

UEFI : 在Linux(Ubuntu)下build UEFI Bios module

為什麼要在Linux(Ubuntu)底下build Bios module呢?
因為接手了大陸同事的UEFI Shell code,而他使用了 gcc 的library "Atomic Memory Access",這個library在平常我們慣用的Visual Studio compiler下無法直接使用。

所以這兩天,花了點時間研究一下如何在Ubuntu下建構可以編譯的環境。
由於網路上比較少有這樣的文章分享, 因此特地新增一篇網誌做說明以及紀錄

基本上我是參考以下這兩篇Using EDK II with Native GCCUDK2014 How to Build
,這邊解釋一下必要的流程

#取得EDK2 code base 請參考 https://github.com/tianocore/edk2

#安裝所需要的編譯工具
bash$:   sudo apt-get install build-essential subversion uuid-dev iasl

#取得nasm組譯器
bash$:   sudo apt-get install nasm

2016年11月23日 星期三

x86 architecture : Graphic UMA Frame buffer

傳統的顯卡控制方式是透過A/B Segment MMIO來輸出螢幕,但只有128K MMIO address, 顯然這樣的空間不夠用。現在的內顯都會在DRAM上"偷"一塊Memory做為輸出顯示用,系統上是看不到這塊Memory的,而這塊Memory稱為UMA frame buffer。一般在系統上看到系統顯示的記憶體遠小於所插的Dram記憶體,一大部分就是被frame buffer挖走的,至於frame buffer的size是可以在Bios選單去改變設定的。

UMA frame buffer之所以特殊是,他宣告為MMIO resource,但實際上decoder會將含有此address的cycle再forward給memory. 示意圖如下:



一般CPU bus的 traffic control 設計通常會先看這筆cycle是否往MMIO (C2P cycle),若不是則再看是否往Memory (C2M cycle),若都不是的話,則透過報錯機制回報錯誤(EBMC, MCA...)。

而外插式顯卡本身有自己的DRAM, 雖然都會要求MMIO resource, 但使用的是自己的記憶體。

Keyword: UMA( Unified Memory Architecture), Frame buffer, Graphic

2016年11月15日 星期二

g++ : libgcc_s_dw2-1.dll is missing

解決某些Windows平台在執行exe檔時,找不到libgcc_s_dw2-1.dll。缺少的這個dll應該是C++的library
我的g++版本(gcc -v): 4.8.1

解決方法就是在compile code 時加入 -static-libgcc  -static-libstdc++ 參數把所需要的library包進去

如下:
g++ -o main main.cpp 改成 
g++ -o main -static-libgcc  -static-libstdc++ main.cpp

2016年11月11日 星期五

使用DeviceIoControl::IOCTL_DISK_GET_LENGTH_INFO 獲取 Disk 大小


一般若要得到Sata硬碟或Usb硬碟Size,須要透過傳遞PASS_THROUGH參數來下Identify command,而參數須符合ATA command/ SCSI command spec, 使用上比較麻煩。

WinApi提供了一個比較通用的方式(IOCTL_DISK_GET_LENGTH_INFO)來得到,如下:



#include <windows.h>
#include <winioctl.h>
#include <stdio.h>

unsigned long long GetDiskLengthIoctl(const char *dsk)
{
  HANDLE hDisk = CreateFile( dsk,
                            GENERIC_READ,
                            FILE_SHARE_VALID_FLAGS,
                            0,
                            OPEN_EXISTING,
                            0,
                            0);
  if(hDisk == INVALID_HANDLE_VALUE)
    {
      printf("Could not open the disk. GetLastError() returned ", GetLastError());
      return 0;
    }
  GET_LENGTH_INFORMATION gli;
  DWORD ret;

  DeviceIoControl( hDisk,
                   IOCTL_DISK_GET_LENGTH_INFO,
                   0,
                   0,
                   &gli,
                   sizeof(gli),
                   &ret,
                   0);

  CloseHandle(hDisk);
  return gli.Length.QuadPart;
}
int main()
{

  const char *Disk = "\\\\.\\PhysicalDrive0"; // or \\\\.\\C:
  printf("size = %d (GB)\n", GetDiskLengthIoctl(Disk)/1024/1024/1024);
  printf("Lba = %x \n", GetDiskLengthIoctl(Disk)/512);

}

2016年8月5日 星期五

ATA : SATA-to-USB and SSD

由於USB的方便攜帶跟普及性,所以現在市售走USB protocol 的外接硬碟非常多,大部分的構造都是一顆SATA硬碟搭配SATA-to-USB  轉卡。還有些人是自行購買SATA-to-USB  轉卡透過USB port來外接硬碟 or SSD。接 SSD這樣的用法是有隱憂的,接下來解釋原因。

以上的架構(SATA過轉卡轉USB), 如果想傳原生的ATA Command給硬碟,則必須穿過  SATA-to-USB  轉卡才能將ATA command傳給碟機。方法是透過呼叫  DeviceIoControl 來發出  SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER以前在硬碟廠寫相關Utility (Update FW/ Identify...), 就是透過這個protocol發出ATA 給硬碟。

能夠在作業系統底下Access碟機,以硬碟廠的角度可以提供FAE做初期的檢測(看Smart table / 下一些Vendor Specific的command來判斷FTL/GC出了什麼樣的問題)當然還有最重要的update FW