Как создать минимальный образ для Raspberry Pi 4 B?
Пытаюсь создать образ для RPi 4 под AArch64. Использовал информацию с OS Dev, но толку нет. В примере по ссылке работа с UART. Я же пытаюсь вывести хоть что-то на экран. На выходе только стандартная "радуга".
Использую почтовый ящик (Mailbox) для получения информации о видеобуфере. Потом пытаюсь заполнить экран белым.
В config.txt есть строка kernel=nose.img
Сам код
constexpr unsigned int MMIO_BASE = 0xFE000000;
constexpr unsigned int MBOX_BASE = MMIO_BASE + 0xB880;
unsigned int * const MBOX_READ = reinterpret_cast<unsigned int * const>(MBOX_BASE + 0x00);
unsigned int * const MBOX_STAT = reinterpret_cast<unsigned int * const>(MBOX_BASE + 0x18);
unsigned int * const MBOX_WRIT = reinterpret_cast<unsigned int * const>(MBOX_BASE + 0x20);
inline void mmioWrite(int reg, int data){
reinterpret_cast<volatile int*>(reg)[0] = data;
}
inline int mmioRead(int reg){
return reinterpret_cast<volatile int*>(reg)[0];
}
constexpr int MAX_MSG_LEN = 36;
constexpr int MBOX_CH_FB = 1;
constexpr int MBOX_FULL = 0x80000000;
constexpr int MBOX_EMPTY = 0x40000000;
constexpr int MBOX_LAST = 0x00000000;
constexpr int MBOX_REQUEST = 0x00000000;
constexpr int MBOX_RESPONSE = 0x80000000;
static int mailBox[MAX_MSG_LEN];
//@0 - length of message
//@1 - type (==MBOX_REQUEST)
//@2 - ID of query
//@3 params (variable length)
constexpr int FB_GET_FBPARAMS = 0x00040001;
constexpr int FB_SET_HW_PARAMS = 0x00048003;
constexpr int FB_SET_SW_PARAMS = 0x00048004;
constexpr int FB_SET_DEPTH = 0x00048005;
constexpr int FB_SET_PMODE = 0x00048006; //pixel order
constexpr int FB_GET_PITCH = 0x00048008;
//mailBoxCall use mailBox array
bool mailBoxCall(int channel){
unsigned int r = (reinterpret_cast<unsigned long>(mailBox) & 0xFFFFFFF0)|(channel&0xF);
do{
asm volatile("nop");
}while(*MBOX_STAT & MBOX_FULL);
*MBOX_WRIT = r;
while(true){
do{
asm volatile("nop");
}while(*MBOX_STAT & MBOX_EMPTY);
if(r == *MBOX_READ){
return mailBox[1]==MBOX_RESPONSE;
}
}
}
char __attribute__((aligned(4096))) sysStack[65536];
extern "C" __attribute__((section(".start"))) int _start(int dtb, int, int, int, int addrOfStart){
asm volatile("mrs x5, mpidr_el1\n and x5, x5, #0xFF\n _hung_: cbnz x5, _hung_");
asm volatile ("mov sp, %0"::"r"(sysStack));
int inx=1;
int * pFrameBuffer=nullptr;
mailBox[inx++]=MBOX_REQUEST;
mailBox[inx++]=FB_GET_FBPARAMS; //tag
mailBox[inx++]=8; //buf len for return value
mailBox[inx++]=8; //len for req value
mailBox[inx++]=4096;
int inxFramebufferAddr = inx-1;
mailBox[inx++]=0;
int inxFramebufferSize = inx-1;
mailBox[inx++]=MBOX_LAST;
mailBox[0]=inx*sizeof(mailBox[0]);
if(mailBoxCall(MBOX_CH_FB)){
pFrameBuffer = reinterpret_cast<int *>(mailBox[inxFramebufferAddr]);
for(int pixel=0; pixel<mailBox[inxFramebufferSize]; pixel++){
pFrameBuffer[pixel]= 0xFFFFFF;
}
}
for(;;);
}
Код скрипта ld
ENTRY(_start)
SECTIONS
{
. = 0x80000;
._start : { *(.start) }
.text : { *(.text) }
.init_arr : ALIGN(4096) {
PROVIDE_HIDDEN(__init_begin = .);
*(.init_array) ;
PROVIDE_HIDDEN(__init_end = .);
}
.fini_arr : ALIGN(4096) {
PROVIDE_HIDDEN(__fini_begin = .);
*(.fini_array) ;
PROVIDE_HIDDEN(__fini_end = .);
}
.data : ALIGN(4096) { *(.data) *(.data.*) }
.strings : ALIGN(4096) { *(.rodata.*) }
.rodata : ALIGN(4096) { *(.rodata) }
.eh_frame : ALIGN(4096) { *(.eh_frame) *(.gcc_except_table) }
.bss : ALIGN(4096) { *(.bss) *(.bss.*) }
/DISCARD/ : { *(.note) *(.note.*) *(.comment) *(.idata) }
.other : ALIGN(4096) { *(*) }
}
Содержимое Makefile (копиляция также на "Малинке"):
GCC=/opt/gcc/bin/aarch64-g++ -x c++ -march=native -g0 -O3 -std=gnu++17 -c -D$(DEBUG) -I$(INCLUDE) \
-nostdlib -nostartfiles -nostdinc -nostdinc++ -undef \
-fmax-errors=5 -free -fPIC -fno-stack-protector -fno-use-cxa-atexit\
-ffreestanding -fsigned-char -funsigned-bitfields -fno-unroll-loops\
-fno-PIE -fshort-wchar -fno-dwarf2-cfi-asm\
-Wall -pedantic -Wno-multichar -Wno-packed-bitfield-compat
LD=/opt/binutils/bin/aarch64-ld -x -nostdlib
objects = $(foreach objfile,$(patsubst %.cpp,%.o,$(wildcard *.cpp)),$(BUILD)/$(objfile))
objects += $(foreach objfile,$(patsubst %.S,%.o,$(wildcard *.S)),$(BUILD)/$(objfile))
headers = $(shell find $(INCLUDE) -type f | grep ".hpp$$")
dirs = $(shell ls -d */ | sed 's:/$$::')
subdirs = $(foreach dir,$(dirs),$(dir).uptime)
.PHONY: all
all: ../nose.img
$(BUILD):
@-mkdir $(BUILD)
$(DBG):
@-mkdir $(DBG)
%.uptime:
@make -C $(shell echo $@ | sed 's:\.uptime$$::' | sed 's:.*/::') -e GCC="$(GCC)" BUILD="$(BUILD)" DBG="$(DBG)"
../nose.img: $(BUILD) $(DBG) $(objects) $(subdirs) ld.script Makefile
@$(LD) -o $@ -T ld.script -d $(BUILD)/*.o
@cp $@ [email protected]
@objdump -s -d [email protected] >[email protected]
@strip --strip-unneeded -K start $@
@objcopy $@ -O binary ../nose.img
$(BUILD)/%.o: %.cpp $(headers)
@echo "GCC\t"$@
@#$(GCC) -S [email protected] $< -o [email protected]
@#mv -f [email protected] $(DBG)
@$(GCC) -S $< -o [email protected]
@mv -f [email protected] $(DBG)
@$(GCC) $< -o $@
$(BUILD)/%.o: %.S
@echo "GCC\t"$@
@#$(GCC) -S [email protected] $< -o [email protected]
@#mv -f [email protected] $(DBG)
@#$(GCC) -S $< -o [email protected]
@#mv -f [email protected] $(DBG)
@$(GCC) $< -o $@
.PHONY: clean
clean:
@make -C dev clean
@make -C collations clean
-@rm -f *.img
-@rm -rf $(BUILD)/
-@rm -rf $(DBG)/
-@rm -f *.dbg
-@rm -f *.dsf
-@rm -f *.log