All this very low level work will of course depend on… the architecture.
For the most common (x86/IBM PC) the BIOS will help a lot for a good start. If you get one, look at your bootlog, it will start querying the BIOS :
BIOS-provided physical RAM map:
further down, you might notice something like :
BIOS-e820: [mem 0x00000000cff80000-0x00000000cff8dfff] ACPI data
which are tables provided by the BIOS on which the OS can rely in order to obtain additional infos about peripherals… (BIOSes are often known to be more or less broken on this)
On the other end you get ARM SoCs with each vendor supporting peripherals its own way (and most often as closed-source) and who, of course, never agreed on whatever BIOS equivalent. This situation led to some famous quotes from Linus Torvald :
I hope the SoC ARM designers die in an incredibly painful accident.
[…] Gaah, Guys this whole ARM thing is a fucking pain in the ass.
If your project is based on that sort of hardware… well… Good luck! You might well have to bruteforce on memory ranges. (Write and consider what happens)
Then come less architecture dependent information data. Those about devices standing on standard buses :
For ISA devices (nowadays mostly serial / parallel ports) you'll need to rely on some trial and error method reading a very limited number of usual port addresses to consider what it looks like.
For devices plugged into PCI buses, the PCI configuration space is a standard which enables the implementation of standard (arch independent) methods for enumerating and initializing.
In any case, if your hardware cannot rely on standardized methods for probing you will be on your own to answer your question as @telcoM suggests it :
On ARM, the standard seems to be that the designers (or
reverse-engineers, as the case may be) of the hardware must describe
it in the form of device tree data, which is then loaded by the
hardware-specific bootloader along with the kernel file and possibly
initramfs file. So if your hardware project uses an architecture that
does not include a standardized, autoprobeable main bus like PCI or
PCIe, then yes, you, the hardware designer will have to provide that
information for the Linux kernel.