I don't know how helpful this is, but here are my usual definitions. For the record, I'm a hardware kinda guy.
* If I can touch it, it's hardware. * If it's made of code/programming, and it's on computer media, inside a computer, or in a ROM chip that runs the system, it's software, *except*... * ...if it's in a chip that isn't a ROM (or acting as ROM), it's firmware. * ...if it's in a ROM chip (or a chip acting as ROM), *and* it's not got the controlling program for the entire system, it's also firmware. * ...if it's hardcopy, it's of course a program listing. * ...if it's not a binary, it's of course source code.
"Acting as a ROM" covers Flash memory (which is technically nonvolatile RAM, aka NVRAM) and systems that (stupidly IMO) use battery-backed static RAM instead of a real ROM -- and other similar schemes that I'm not aware of.
The 'if it's in a ROM chip and it runs the system, it's software' idea covers systems that run an OS from ROM, whether or not they act as one would recognize a computer in the modern sense. (It specifically excludes the PC BIOS, though, and things like it.) That covers eg the Commodore 64 --and, in fact, most late-'70s and '80s computers-- but it also covers the 6502-based system I'm using to learn a bit about how those are programmed at an assembly level, even though *that* system's entire purpose and function is to push a hard-coded ASCII message to a weird TTL-serial LCD I own. Some argument could be made that I should shut up and toss these use cases in with firmware, but for some reason I can't adequately explain, that somehow doesn't feel right.