Issues with bootloader - macos

I am in the process of learning Assembly, and I tried writing my own bootloader. It works fine on VirtualBox , but it doesn't work on a actual PC.
On pc 'Hello World!' doesn't get printed.
This is the code is use:
BITS 16
ORG 0x7C00
jmp boot_sector
;------------------------------
OEMLabel db "FLOPPYDR"
BytesPerSector dw 512
SectorsPerCluster db 1
ReservedForBoot dw 1
NumberOfFats db 2
RootDirEntries dw 224
LogicalSectors dw 2880
MediumByte db 0xF0
SectorsPerFat dw 9
SectorsPerTrack dw 18
Sides dw 2
HiddenSectors dd 0
LargeSectors dd 0
DriveNo dw 0
Signature db 41
VolumeID dd 0x00
VolumeLabel db "FLOPPYDRIVE"
FileSystem db "FAT12"
;##############################
boot_sector:
;##############################
mov ax, 0x0000 ; Set up the stack
mov ss, ax ; Is this done correctly?
mov sp, 0x7C00 ; (I dont quite understand)
int 0x10 ; Set video mode
int 0x13 ; Reset the drive
mov ah, 0x02 ; Read more sectors
mov al, 2 ; Read two extra sectors,
mov bx, main_sector ; starting from the second.
mov ch, 0 ;
mov cl, 2 ; dl has been set already (?)
mov dh, 0 ;
int 0x13 ;
mov [bootdev], dl ; Store original dl in bootdev
jmp main_sector ; Go to the main sector (0x200 I think)
times 510 - ($ - $$) db 0 ; Fill in the rest of the sector with 0s
dw 0xAA55 ; and 0xAA55 at the end for signature
;##############################
main_sector:
;##############################
jmp Start
;------------------------------
bootdev db 0
msg db 'Hello World!', 10, 13, 0
;------------------------------
print_string:
mov ah, 0x0E
mov bh, 0
cmp al, 0
jne .loop
mov bl, 0x0F
.loop:
lodsb
cmp al, 0
je .end
int 0x10
jmp .loop
.end:
ret
;------------------------------
Start:
mov si, msg
call print_string
hlt
times 512 - ($ - main_sector) db 0
I've also commented in some questions, but these are not my main question (well, maybe me not knowing the answer causes the problem). Why doesn't this work on a real PC?
To compile I use nasm -f bin boot.asm -o boot.bin and to create a virtual floppydisk file I use mkfile 1474560 floppy.flp
Then I open up floppy.flp using HexEdit and replace the first 64 lines (0x00 - 0x3F) with the content of the boot.bin file (opened using HexEdit).
E9 38 00 46 4C 4F 50 50 59 44 52 00 02 01 01 00
02 E0 00 40 0B F0 09 00 12 00 02 00 00 00 00 00
00 00 00 00 00 00 29 00 00 00 00 46 4C 4F 50 50
59 44 52 49 56 45 46 41 54 31 32 B8 00 00 8E D0
BC 00 7C CD 10 CD 13 B4 02 B0 02 BB 00 7E B5 00
B1 02 B6 00 CD 13 88 16 03 7E E9 A3 01 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA <-- End of first sector
E9 24 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 21
0A 0D 00 B4 0E B7 00 3C 00 75 02 B3 0F AC 3C 00
74 04 CD 10 EB F7 C3 BE 04 7E E8 E6 FF F4 00 00 (The rest is just 0's).
This is the Terminal when I burn floppy.flp to the USB drive:
Last login: Wed Sep 23 12:10:48 on ttys000
MacBook-Air:~ sasha$ cd ~/Desktop
MacBook-Air:Desktop sasha$ diskutil list
/dev/disk0
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme *121.3 GB disk0
1: Apple_HFS 209.7 MB disk0s1
2: Apple_CoreStorage 120.5 GB disk0s2
3: Apple_Boot Recovery HD 650.0 MB disk0s3
/dev/disk1
#: TYPE NAME SIZE IDENTIFIER
0: Apple_HFS Macintosh HD *120.1 GB disk1
Logical Volume on disk0s2
8CD6A846-395D-4C97-A5DE-0A7ABA9F1C99
Unencrypted
/dev/disk2
#: TYPE NAME SIZE IDENTIFIER
0: Apple_partition_scheme *17.1 MB disk2
1: Apple_partition_map 32.3 KB disk2s1
2: Apple_HFS Flash Player 17.1 MB disk2s2
/dev/disk3
#: TYPE NAME SIZE IDENTIFIER
0: FLOPPYDRIVE *1.0 GB disk3
MacBook-Air:Desktop sasha$ diskutil unmountdisk /dev/disk3
Unmount of all volumes on disk3 was successful
MacBook-Air:Desktop sasha$ sudo dd bs=512 if=floppy.flp of=/dev/disk3
Password:
2880+0 records in
2880+0 records out
1474560 bytes transferred in 0.843982 secs (1747146 bytes/sec)
MacBook-Air:Desktop sasha$

I've written about bootloaders at some length recently on Stackoverflow. Most issues that involve the situation where it works on one emulator or VM but not on another (or physical hardware) usually come down to making false assumptions about the state of the segment registers when the BIOS jumps to your code. Under some emulators the segment registers may have more sane values in them, but that usually isn't the case. From my previous answer I had these two tips that seem to apply here:
When the BIOS jumps to your code you can't rely on DS,ES,SS,SP registers having valid or expected values. They should be set up appropriately when your bootloader starts.
The direction flag used by lodsb, movsb etc could be either set or cleared. If the direction flag is set improperly SI/DI registers may be adjusted in the wrong direction. Use STD/CLD to set it to the direction you wish (CLD=forward/STD=backwards). In this case the code assumes forward movement so one should use CLD. More on this can be found in an instruction set reference
Your assembly code is set to compile and link assuming an origin point of 0x7C00 (via ORG 0x7C00). Your code that accesses variables like msg and bootdev will be made with the assumption that their memory address will be absolute within the segment (DS). This means that if you have an invalid DS segment then you could be addressing variables, data, and labels at the wrong locations. As an example:
mov [bootdev], dl
has an implicit reference to DS and is equivalent to addressing it with an explicit DS segment:
mov [ds:bootdev], dl
If DS has some random value in it then you'll likely be accessing memory in places you don't expect. For some environments DS might just be zero so your code will work.
How do you know which segment to use? The bootloader is loaded by the BIOS at physical memory 0x0000:0x7C00(segment:offset) . Your origin point (Set with ORG directive) matches the offset so that means in your case DS should be set to zero.
In your code ES should also be set to zero. The reason is that INT 0x13 AH=0x02 (disk read) says:
ES:BX Buffer Address Pointer
Imagine if ES is set to random garbage, the disk read will likely read into memory you didn't intend. So just like DS, ES must also be set. You've written your bootloader and kernel in the same file with the origin point of 0x7C00 so again you just need to use an ES segment set to zero.
When setting up your stack you can set ES and DS appropriately.
mov ax, 0x0000 ; Set up the stack
mov ss, ax ; Is this done correctly?
mov sp, 0x7C00 ; (I dont quite understand)
mov ds, ax ; Set DS to 0 because that is what your code needs
mov es, ax ; ES the same as DS.
cld ; Read my tip #2
You did ask if you set your stack properly. There is nothing wrong with it. Your instructions effectively set up a a stack that grows downward from 0x0000:0x7C00 just below the area occupied by your bootloader. That leaves about 27kb (0x7C00-0x1000) of stack space. 4k is plenty for BIOS calls and your current code. The first 0x1000 of memory are generally for interrupt table/BIOS data area etc.
One other bug I noticed in your code was when you try to reset the disk drive:
int 0x10 ; Set video mode
int 0x13 ; Reset the drive
You set AX to zero above these 2 lines. INT 0x10 AH=0x00 (set video mode) has the side effect of returning information in AX. Since AX can be clobbered your call to INT 0x13 AH=0x00 will likely be wrong. You need to clear AH (or all of AX) prior to calling int 0x13 to reset the drive. The code should look like:
int 0x10 ; Set video mode
xor ax,ax ; clear AX (AH=0)
int 0x13 ; Reset the drive
There is a minor issue at the top of your program and would likely only be a problem if you put this bootloader on a properly formatted FAT12 disk image and tried to mount it in your OS. You have:
jmp boot_sector
;------------------------------
OEMLabel db "FLOPPYDR"
The disk structure you have within your bootloader should have OEMLabel starting from the 4th byte. jmp boot_sector could be encoded as a 2 or 3 byte instruction by NASM. Use short to force a 2 byte encoding followed by a NOP (1 byte instruction). This will place OEMLabel at the 4th byte in the file. It could look like this:
jmp short boot_sector
nop
;------------------------------
OEMLabel db "FLOPPYDR"
Alternatively you can encode a JMP that may be 2 or 3 bytes when encoded and pad it with NOP if necessary using NASM's TIMES directive so that OEMLabel always starts at the 4th byte:
jmp boot_sector
times 3-($-$$) nop
;------------------------------
OEMLabel db "FLOPPYDR"
A trick to avoid using hexedit to manually insert the bootloader code at the beginning of a disk image is to use dd. You can use dd to overwrite the first 1024 bytes and keep the rest intact. Try dd if=boot.bin of=floppy.flp bs=512 count=2 conv=notrunc . This should open up floppy.flp write 2 512 byte sectors containing the 1024 bytes from boot.bin without truncating the file (conv=notrunc)

When a bootloader is started the contents of almost all registers (including segment registers) is "undefined". The only register that actually does have a known value is DL (which contains the BIOS' drive number for the disk).
All instructions that refer to memory use an implied or explicit segment register. For example, both mov [bootdev], dl and lodsb rely on the (implied) DS segment register, which is never set and is still undefined.
Like all undefined values, it's possible (due to pure luck) for them to be a value that makes things work by accident. Your code would work if the BIOS happened to leave the value 0x0000 in DS.

Related

Lattice ECP5 UART, no signal on terminal emulator

I followed this tutorial to the letter, but I'll to explain in detail what steps I took exactly. I have an ECP5-evaluation 85k board.
I soldered bridges on R34/R35 (RX/TX) and R21 (connects LED D1 to RXD)
I used my windows installation to run the latest version of FT_PROG. In FT_PROG I went to FT_EEPROM -> Hardware Specific -> Port B -> Hardware and set it to RS232 and hit program. It completed succesfully according to the software.
Then I forwarded the USB port to my virtual box linux machine. It recognizes the board and I can succesfully run verilog files on it.
I ran ./raw_serial.sh to upload raw_serial.v to my board which is supposed to repeatedly print A to the serial monitor.
I then opened minicom on /dev/ttyUSB1 and it recognizes the device, baudrate is set correctly.
I then tried to use cu as follows: sudo chmod 666 /dev/ttyUSB1 && sudo cu -l /dev/ttyUSB2 -s 115200. It opens a terminal and says it is connected.
Led D1 is lighting up and both terminal programs indicate that the connection is succesful (I tried one of them at a time of course). Nothing is printed to the screen. When I use minicom and reupload raw_serial.v some <?> signs are printed to the screen but that's it. I tried turning echo on and off but nothing seems to work.
The following worked for me and it will probably work for others too. I'm assuming you're using openocd.
Do not use FT_PROG in windows, it doesn't seem to actually flash the FTDI chip. However, it lets you read back the hex dump that was supposed to be flashed to the chip. The hex dump for the unchanged EEPROM as it comes out of the box is as follows:
00000000 01 08 03 04 10 60 00 07 C0 FA 08 00 11 11 9A 10 .....`..Àú....š.
00000010 AA 3C E6 12 00 00 00 00 56 00 00 00 00 00 00 00 ª<æ.....V.......
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050 00 00 00 00 00 00 02 03 00 00 00 00 00 00 00 00 ................
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090 00 00 00 00 00 00 00 00 00 00 10 03 4C 00 61 00 ............L.a.
000000A0 74 00 74 00 69 00 63 00 65 00 3C 03 4C 00 61 00 t.t.i.c.e.<.L.a.
000000B0 74 00 74 00 69 00 63 00 65 00 20 00 45 00 43 00 t.t.i.c.e. .E.C.
000000C0 50 00 35 00 20 00 45 00 76 00 61 00 6C 00 75 00 P.5. .E.v.a.l.u.
000000D0 61 00 74 00 69 00 6F 00 6E 00 20 00 42 00 6F 00 a.t.i.o.n. .B.o.
000000E0 61 00 72 00 64 00 12 03 46 00 54 00 32 00 55 00 a.r.d...F.T.2.U.
000000F0 59 00 54 00 4A 00 56 00 00 00 00 00 00 00 FC 27 Y.T.J.V.......ü'
I just post this here for future reference, we're not going to use the stock eeprom.
We need to flash the eeprom to RS232-HS mode. To do so, we must first change the hex dump of the eeprom accordingly. To put channel B in RS232-HS mode we need to change the last column of the last row from ' to |. Create a hex file called eeprom_RS232.bin with the following contents:
00000000 01 08 03 04 10 60 00 07 C0 FA 08 00 11 11 9A 10 .....`..Àú....š.
00000010 AA 3C E6 12 00 00 00 00 56 00 00 00 00 00 00 00 ª<æ.....V.......
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050 00 00 00 00 00 00 02 03 00 00 00 00 00 00 00 00 ................
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090 00 00 00 00 00 00 00 00 00 00 10 03 4C 00 61 00 ............L.a.
000000A0 74 00 74 00 69 00 63 00 65 00 3C 03 4C 00 61 00 t.t.i.c.e.<.L.a.
000000B0 74 00 74 00 69 00 63 00 65 00 20 00 45 00 43 00 t.t.i.c.e. .E.C.
000000C0 50 00 35 00 20 00 45 00 76 00 61 00 6C 00 75 00 P.5. .E.v.a.l.u.
000000D0 61 00 74 00 69 00 6F 00 6E 00 20 00 42 00 6F 00 a.t.i.o.n. .B.o.
000000E0 61 00 72 00 64 00 12 03 46 00 54 00 32 00 55 00 a.r.d...F.T.2.U.
000000F0 59 00 54 00 4A 00 56 00 00 00 00 00 00 00 FC 27 Y.T.J.V.......ü|
Now, we need to flash this eeprom to our ECP5 using Anton's method. To do this, first create a file ftdi_RS232.conf with the following contents:
vendor_id=0x403
product_id=0x6010
filename="eeprom_RS232.bin"
flash_raw=true
With the following command we can flash to our ECP5: ftdi_eeprom --flash-eeprom ftdi_RS232.conf. Should we ever want to revert back to the stock eeprom, we can easily repeat this method with the hex dump given in step 1.
Now it's time to flash the verilog file. However, the device description of the ECP5 has changed from Lattice ECP5 Evaluation Board to Dual RS232-HS. We need to tell openocd to look for that specific device. Start by creating a file ecp5.cfg with the following contents:
# this supports ECP5 Evaluation Board
interface ftdi
ftdi_device_desc "Dual RS232-HS"
ftdi_vid_pid 0x0403 0x6010
# channel 1 does not have any functionality
ftdi_channel 0
# just TCK TDI TDO TMS, no reset
ftdi_layout_init 0xfff8 0xfffb
reset_config none
# default speed
adapter_khz 5000
# ECP5 device - LFE5UM5G-85F
jtag newtap ecp5 tap -irlen 8 -expected-id 0x81113043
Then, create your svf file as you usually do and flash it with the following command:
sudo --preserve-env=PATH env openocd -f ./ecp5.cfg -c "transport select jtag; init; svf raw_serial.svf; exit"
Finally, we can open a terminal to read the serial output of the ECP5. Personally, I like to use minicom: sudo chmod 666 /dev/ttyUSB0 && minicom -D /dev/ttyUSB0.
One more problem with the raw_serial.v example was that it doesn't use a baudrate of 115200 as the readme suggests but 19200. The clock that is connected to the FTDI chip runs at 12 MHz. If you want a baudrate of 115200 you need to send a bit every 12,000,000 / 115,200 ~= 104 ticks. This means you need to change line 14 to if (counter == 104) begin.

ELF Executable Segfaults

I've been trying to create an ELF executable using libelf, but haven't gotten it running yet. Whenever I try to run it, I just get a segfault. strace outputs:
execve("./test.elf", ["./test.elf"], 0x7ffc28d60660 /* 63 vars */) = -1 EINVAL (Invalid argument)
+++ killed by SIGSEGV +++
readelf gives:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1000
Start of program headers: 64 (bytes into file)
Start of section headers: 152 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 1
Size of section headers: 64 (bytes)
Number of section headers: 3
Section header string table index: 2
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000001000 00000078
0000000000000008 0000000000000000 AX 0 0 1
[ 2] .shstrtab STRTAB 0000000000000000 00000080
0000000000000011 0000000000000000 A 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000078 0x0000000000001000 0x0000000000001000
0x0000000000000008 0x0000000000000008 R E 0x1
Section to Segment mapping:
Segment Sections...
00 .text
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
No version information found in this file.
And here's the hexdump of the file:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 3e 00 01 00 00 00 00 10 00 00 00 00 00 00 |..>.............|
00000020 40 00 00 00 00 00 00 00 98 00 00 00 00 00 00 00 |#...............|
00000030 00 00 00 00 40 00 38 00 01 00 40 00 03 00 02 00 |....#.8...#.....|
00000040 01 00 00 00 05 00 00 00 78 00 00 00 00 00 00 00 |........x.......|
00000050 00 10 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................|
00000060 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |................|
00000070 01 00 00 00 00 00 00 00 31 c0 ff c0 b3 2a cd 80 |........1....*..|
00000080 00 2e 74 65 78 74 00 2e 73 68 73 74 72 74 61 62 |..text..shstrtab|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000000d0 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................|
000000e0 06 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................|
000000f0 78 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |x...............|
00000100 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 07 00 00 00 03 00 00 00 |................|
00000120 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000130 80 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 |................|
00000140 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 |........|
00000158
From what I've read and comparing it to working executables, this should work. But it doesn't, and I have no idea why. Any help is appreciated, thanks.
I figured it out! When I was looking at a working executable for reference, I was looking at a PIE, but I was trying to create a non-PIE. I didn't realize the EHDR type needs to be ET_DYN for a PIE. Also, a few of the addresses were wrong.
The new readelf:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1078
Start of program headers: 64 (bytes into file)
Start of section headers: 152 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 1
Size of section headers: 64 (bytes)
Number of section headers: 3
Section header string table index: 2
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000001078 00000078
0000000000000008 0000000000000000 AX 0 0 1
[ 2] .shstrtab STRTAB 0000000000000000 00000080
0000000000000011 0000000000000000 A 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000078 0x0000000000001078 0x0000000000001078
0x0000000000000008 0x0000000000000008 R E 0x1
Section to Segment mapping:
Segment Sections...
00 .text
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
No version information found in this file.
And the new hexdump:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 03 00 3e 00 01 00 00 00 78 10 00 00 00 00 00 00 |..>.....x.......|
00000020 40 00 00 00 00 00 00 00 98 00 00 00 00 00 00 00 |#...............|
00000030 00 00 00 00 40 00 38 00 01 00 40 00 03 00 02 00 |....#.8...#.....|
00000040 01 00 00 00 05 00 00 00 78 00 00 00 00 00 00 00 |........x.......|
00000050 78 10 00 00 00 00 00 00 78 10 00 00 00 00 00 00 |x.......x.......|
00000060 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |................|
00000070 01 00 00 00 00 00 00 00 31 c0 ff c0 b3 2a cd 80 |........1....*..|
00000080 00 2e 74 65 78 74 00 2e 73 68 73 74 72 74 61 62 |..text..shstrtab|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000000d0 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................|
000000e0 06 00 00 00 00 00 00 00 78 10 00 00 00 00 00 00 |........x.......|
000000f0 78 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |x...............|
00000100 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 07 00 00 00 03 00 00 00 |................|
00000120 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000130 80 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 |................|
00000140 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 |........|
00000158

How to access the I/O bits of PCI printer card?

In older time on a P4 mother board of my PC there was an integrated parallel printer port with a DB-25 connector. These I/O pins was very handy to communicate with an external digital equipment.
I could use these I/O pins to control my external hardware from my C programs under Linux because:
I knew the I/O map on 0x378 or 0x278, and I used the ioperm(0x378,2,1) function to give privilege to direct access under Linux.
After it I could simple write and read with outb(data, 0x378), inb(0x378+1) functions (with #include <sys/io.h> ). (I have it run with root privilege or I used the setuid rights).
But now I have a newer mother board GA-870A-USB3 without any parallel port.
I bought a parallel PCI card seems on the picture.
I had to choose PCI interface due to mother board.(I think with ISA bus I wouldn't any problem but today no ISA bus on the motherboard.)
Can I access the DB-25 pins on this PCI printer card under Linux from my C programs in the same way as above or how could I use this card's I/O pins? (The preferable bit changing speed is about .5-1 ms. This bite rate is easily performed with an old P4 mother board on the default parallel port (0x378). Although my communication protocol of my hardware isn't sensible for bit rate.)
Cont. at Oct 5.
I plugged and unplugged the above PCI I/O card and I could realize that this line
03:06.0 Serial controller: TXIC Device 5073 (rev 10)
is related for my card.
Here is a detailed list:
lspci -vvvxxxs 03:06.0
03:06.0 Serial controller: TXIC Device 5073 (rev 10) (prog-if 02 [16550])
Subsystem: TXIC Device 3273
Control: I/O+ Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Interrupt: pin A routed to IRQ 20
NUMA node: 0
Region 0: I/O ports at cf00 [size=8]
Region 1: I/O ports at ce00 [size=8]
Region 2: I/O ports at cd00 [size=8]
Region 3: I/O ports at cc00 [size=8]
Kernel driver in use: serial
00: 51 46 73 50 01 00 00 02 10 02 00 07 00 00 00 00
10: 01 cf 00 00 01 ce 00 00 01 cd 00 00 01 cc 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 51 46 73 32
30: 00 00 00 00 00 00 00 00 00 00 00 00 03 01 00 00
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
80: 51 46 73 50 01 00 00 02 10 02 00 07 00 00 00 00
90: 01 cf 00 00 01 ce 00 00 01 cd 00 00 01 cc 00 00
a0: 00 00 00 00 00 00 00 00 00 00 00 00 51 46 73 32
b0: 00 00 00 00 00 00 00 00 00 00 00 00 03 01 00 00
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Is it normal that there is only one record for this I/O card,
but this card occupies two serial and one parallel port ?
I can see there are some pretty docs from writing device driver:
https://lwn.net/Kernel/LDD3/
https://www.kernel.org/doc/html/latest/PCI/pci.html#
But I hope that I can access my I/O card from user context with my C prg.
I have installed PCI Utilities package:pciutils-3.7.0.tar.gz
from: https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git
I have run the example.c from user context with root user and I could
get a similar list as lspci's.
Would it be a right plan to access I/O card ?
I think this is my main problem: How could I know the meaning of the 256 bytes of my PCI card ?
I think they provides the control/status and data transfer for two serial and one parallel interface.

SSH: Understanding Algorithm Negotiation

I'm currently writing an ssh honeypot in Java as a personal project. I'm having trouble understanding the algorithm negotiation. To be precise, the structure of the received data from the client. Here is what I receive, with my personal annotations:
00 00 07 AC == packet length
08 == padding length
14 == SSH_MSG_KEXINIT
6C 31 89 77 EB 54 E1 8B D4 B1 35 08 FD 52 65 6E == cookie
00 00 00 D4 == string length
kex algorithms in byte form
00 00 01 67 == string length
server host key algorithms in byte form
00 00 00 E9 == string length
encryption_algorithms_client_to_server in byte form
00 00 00 E9 == string length
encryption_algorithms_server_to_client in byte form
00 00 01 92 == string length
mac_algorithms_client_to_server in byte form
00 00 01 92 == string length
mac_algorithms_server_to_client in byte form
00 00 00 1A == string length
compression_algorithms_client_to_server in byte form
00 00 00 1A == string length
compression_algorithms_server_to_client in byte form
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Information about the negotiation can be found here:
rfc4253
There are two things I don't fully understand:
The padding: How is it calculated? According to rfc4253, there should be a random padding (8 bytes in this case). I don't see it anywhere. Moreover, the size of the packet length + padding length + payload + padding should be a multiple of 8, which isn't the case here. (?)
The packet length: If I just sum up everything after the packet length, I get 0x797. Adding the 8 byte padding (wherever it is), I get 0x79F. Am I correct in thinking that the languages for client->server and server->client, although not defined, still take 4 byte each? That gets me to 0x7A7. If I now add the boolean and the reserved 4 bytes (see packet structure), I finally get 0x7AC. Is that correct? That would mean the trailing zeros have the following structure:
00 00 00 00 == length of string for language_client_to_server
00 00 00 00 == length of string for language_server_to_client
00 == boolean first_kex_packet_follows
00 00 00 00 == reserved
rest: garbage?

Why do setpci and lspci -xxxx show different data for the same address?

On my x86 Linux system reading from different locations in PCI configuration space using setpci seems to give completely different answers for some registers when compared to output from lspci -xxxx.
For example, I pick an arbitrary device on my bus and do lspci -s 00:1f.3 -xxxx and get:
00: 86 80 22 1e 03 00 80 02 04 00 05 0c 00 00 00 00
10: 04 40 51 d0 00 00 00 00 00 00 00 00 00 00 00 00
20: a1 ef 00 00 00 00 00 00 00 00 00 00 28 10 8b 05
...
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0: 00 00 00 00 00 00 00 00 87 0f 04 08 00 00 00 00
Now, the output from setpci -s 00:1f.3 0x40+0.l is 02800003 which is consistent with the output above. However, the output from setpci -s 00:1f.3 0xf8+0.l is ffffffff which from the dump above I would have expected to be 08040f87.
Can someone please help shed some light on what is going on here. I'm new to the world of PCI debugging, so I may be missing something obvious here.
Thanks in advance.
man setpci
setpci is a utility for querying and configuring PCI devices.
Root privileges are necessary for almost all operations, excluding reads of the standard header of the configuration space on some operating systems. Please see lspci(8) for details on access rights.
Try as a Super-user

Resources