EEVblog Electronics Community Forum

Products => Computers => Programming => Topic started by: DiTBho on May 06, 2023, 09:03:40 pm

Title: gcc asm inline port in/out in x86 protected mode
Post by: DiTBho on May 06, 2023, 09:03:40 pm
Code: [Select]
static void port_out
(
    uint16_t port,
    uint8_t value
)
{
    asm volatile ("outb %0, %1" : : "a" (value), "Nd" (port));
}

static uint8_t port_in
(
    uint16_t port
)
{
    uint8_t ans;

    asm volatile ("inb %1, %0" : "=a" (ans) : "Nd" (port));
    return ans;
}

is this stuff correct when the x86-CPU is in protected mode?  :o :o :o
(32bit)
Title: Re: gcc asm inline port in/out in x86 protected mode
Post by: magic on May 07, 2023, 05:17:53 am
Seems about right if you didn't swap the operands or something, not sure how the silly AT&T syntax works for these instructions.

Of course they are still valid instructions in protected mode. Pretty sure it should work in long mode too.
Title: Re: gcc asm inline port in/out in x86 protected mode
Post by: Nominal Animal on May 07, 2023, 08:51:09 am
There are two details to consider:
Title: Re: gcc asm inline port in/out in x86 protected mode
Post by: DiTBho on May 07, 2023, 10:08:13 am
thanks, guys

I don't like x86(1) at all, but I am writing a special monitor for my Soekris net5501.
So it's something that boots in real-mode (pure assembly code) and then switches into protected-mode (pure assembly code but jumping into crt0, and then to C main).

Code: [Select]
MBR boot, CPU in 16-bit Mode
CHS loading sec2-10 ... done
console=/serial0,115200-8-n-1
Switching to 32-bit Mode ... done
Installing ISRs ... done
Enabling external interrupts ... done
Initializing dynamic memory ... done
suppa shell
 > help
hallo - if you see the reply, it means it's starting to work
halt  - halt the CPU
 >

the above two in/out x86-port functions are needed to write the serial driver (drivers/serial.c)


(1) actually it's an AMD Geode LX @ 500Mhz
compatible with x86-i586  :-//
Title: Re: gcc asm inline port in/out in x86 protected mode
Post by: Nominal Animal on May 07, 2023, 11:00:43 am
AFAIK you can use grub2 or syslinux/extlinux to boot Soekris net5501.

For grub2, the LHS and CHS geometry must match, because the BIOS uses CHS for small drives and LHS for larger ones.  And you may need to set some option to make sure grub does not wait forever if there is no serial (terminal) connected.

In case you're not aware, this (http://debian.takhis.net/soekris/soekris.html) and this (https://forums.gentoo.org/viewtopic-t-1081484-start-0.html) and this (https://wiki.ubuntu.com/Soekris) may be useful.
Title: Re: gcc asm inline port in/out in x86 protected mode
Post by: magic on May 07, 2023, 11:08:11 am
There are apparently some mechanism for permitting I/O port access by unprivileged tasks so it's not that simple. Wouldn't be surprised if they were used by Windows 98 to run DOS programs or the various VXD drivers.

But in ring 0 you don't care.

https://www.felixcloutier.com/x86/out (https://www.felixcloutier.com/x86/out)
Title: Re: gcc asm inline port in/out in x86 protected mode
Post by: Nominal Animal on May 07, 2023, 11:59:32 am
There are apparently some mechanism for permitting I/O port access by unprivileged tasks
On other rings, the task state segment (https://en.wikipedia.org/wiki/Task_state_segment) can contain a pointer to a bitmap where nonzero bits allow the current task access to said port.  This is not a kernel facility, it is provided by the x86 protected mode itself.

This is used in for example Linux via the ioperm() (https://man7.org/linux/man-pages/man2/ioperm.2.html) kernel interface; the permission/bitmap is retained over an exec.  The ioperm() call itself requires either root privileges or the CAP_SYS_RAWIO capability.
Title: Re: gcc asm inline port in/out in x86 protected mode
Post by: DiTBho on May 07, 2023, 12:23:23 pm
grub2 to boot Soekris net5501.

.... on the last dumpster dive my friends found qty=6 Soekris net5501, most completely smashed as if hit by a giant heavy hammer (wtf?!? why?.?.?), some rusted and with popped caps, plus oxidation from being exposed to rain for months, but the last unit was promising: it powered up, and despite the serial port looked drunk as it outputted strings with missing or weird chars, I found it was only a pin with a floating ground connection.

The mobo was cleaned, easily repaired and finally re-installed into its still rusty metal case waiting to be repainted, but it's back to working condition  :-+


Yub, grub is an option, and it can be configured to reassign the console to Com1 but
- I don't like it
- I also need a monitor, not only a bootloader
- so I want something like U-boot
- I don't want to deal with PC_part
- I don't want to deal with EFI_part
- I need to initialize special PCI-fpga stuff (the net5501 offers a PCI 3.3V slot)
- I want to tftpboot

For grub2, the LHS and CHS geometry must match, because the BIOS uses CHS for small drives and LHS for larger ones.

I think I will use the BIOS disk calls (CHS) only to load the second stage, then I will implement a PCI driver to access the PATA controller in order to directly access the disk in LBA mode.

And in LBA, it will load the kernel in ram, and jump into kernel_start.

I already have a working skeleton
- MBR: working
- disk CHS: working
- second stage: partially working
- monitor (ram-dump, edit, fill): partially completed
- micro shell: partially completed
- serial console: working
- dynamic ram: working

The max size of the final code must be < 800Kbyte  :o :o :o
Title: Re: gcc asm inline port in/out in x86 protected mode
Post by: Nominal Animal on May 07, 2023, 01:41:07 pm
I think I will use the BIOS disk calls (CHS) only to load the second stage, then I will implement a PCI driver to access the PATA controller in order to directly access the disk in LBA mode.
I recommend having /boot be a separate partition at the beginning of the disk.  Then, as long as your CHS geometry matches the LBA mode, it'll just work.

Soekris net5501 was apparently widely used with old Ubuntu and Gentoo versions, so you'll find quite a lot of information there.  Furthermore, if you set up an image with an old distro that supported net5501 out of the box, you can boot it and compare /proc and /sys pseudofiles to see if your custom kernels (kernel configs) have all the necessary/useful options selected.