What I specifically want know here is irrespective of the underlying hardwares it is on how Linux kernel manages to work on all different pcs
Before anything else, the kernel can run on any PC as long it's compiled for that specific architecture. With your general purpose computers, the architecture tends to be the same (x86_64/amd64) but this changes when you're dealing with embedded devices.
Other than compilation, the kernel itself is hardware agnostic. I give you the device-tree!
The way the linux kernel takes care of non-discoverable hardware is through the device-tree. This tells the kernel information about the CPU, memory, buses, devices connected over I2C, SPI and what not. Instead of the device layout being hard-coded, it can be changed through the device-tree. It's all really magical when you understand it. The device-tree also tells the kernel which driver it should use for a specific device through the
The device-tree can be stored in all sorts of different ways depending on how the kernel was compiled but generally the hierarchy can be seen under
For things like USB devices, it's all taken care of by the USB driver. The kernel has basic code for controlling things like keyboards and mice. Some vendors have custom drivers which is then shipped with the device.
For drivers, the linux kernel uses something called kernel modules. All the modules can be found under
/lib/modules. There are two types of modules: loadable modules and built-in modules. You can view all the loaded modules using the
lsmod command. When the kernel finds a certain device in the device-tree or even when you plug a device into a peripheral, it'll look to see if there's a module it can load for that device and the module becomes the driver for that device.
The nice thing about loadable modules is that it keeps the kernel image smaller. The modules can be compiled separately. Built-in modules get compiled into the kernel and thus increases the actual image size. You can also compile and load modules into the kernel while it's running but that's a whole different topic.
You get into BSP's (Board Support Package) when a vendor ships the kernel and a bunch of specific modules for their own hardware (this includes the processor and connected hardware). Sometimes vendors make changes to existing modules or ship custom modules with the kernel. Some vendors have changes made to the kernel itself and that whole custom package becomes the BSP. This happens a lot in the embedded world.
HAL (Hardware Abstraction Layer) can be synonymous to BSP. I haven't seen it being used all that much in the linux world but when you get into microcontrollers, it's used quite often. Essentially, the HAL is a bunch of libraries used to access the hardware, making interfacing with the hardware a lot easier. For example, with a wifi chip, it'll give you basic routines to connect to an AP, scan the network, create an access point e.t.c. It kinda acts a driver in that sense.